// file: $(NEDC_NFC)/class/cpp/Edf/edf_04.cc // // This file contains filename manipulation methods. // // Revision History: // // 20240307 (JP): refactored code to expand set/get methods // // local include files // #include "Edf.h" //***************************************************************************** // // public methods: filename methods // //***************************************************************************** // method: trans_filename // // arguments: // char* tdir: transformed directory (output) // char* tname: transformed filename (output) // char* iname: the input filename (input) // char* odir: the "output" directory name // char* rdir: the replace directory name // // this method applies a bunch of rules to try to construct a new // directory name from several inputs. the logic is straightforward: // // (1) odir == null, rdir == null: split the filename into dir and base // (2) odir == null, rdir != null: delete rdir from iname // (3) odir != null, rdir == null: return idir and iname // (4) odir != null, rdir != null: return idir and remove rdir from iname // // Since the logic of this method is a bit complicated, here are // the use cases: // // odir = desired output directory (/foo/mary) // rdir = replace directory (/data/isip) // input = /data/isip/tmp/joe.edf -or- joe.edf -or- /foo/mary/joe.edf // // 1) odir == null, rdir == null // /data/isip/tmp/joe.edf => /data/isip/tmp/joe.edf // joe.edf => ./joe.edf // /foo/mary/joe.pdf => /foo/mary/joe.edf // // 2) odir = null, rdir == /foo/mary // /data/isip/tmp/joe.edf => /data/isip/tmp/joe.edf // joe.edf => ./joe.edf // /foo/mary/joe.pdf => ./joe.edf // // 3) odir == /foo/mary, rdir == null // /data/isip/tmp/joe.edf => /foo/mary/data/isip/tmp/joe.edf // joe.edf => /foo/mary/joe.edf // /foo/mary/joe.pdf => /foo/mary/joe.edf // // 4) odir == /foo/mary, rdir == /data/isip // /data/isip/tmp/joe.edf => /foo/mary/tmp/joe.edf // joe.edf => /foo/mary/joe.edf // /foo/mary/joe.pdf => /foo/mary/joe.edf // bool Edf::trans_filename(char* tdir_a, char* tname_a, const char* iname_a, const char* odir_a, const char* rdir_a) { // split the input filename into a directory and base // char* str = rindex((char*)iname_a, (char)Itgl::SLASH[0]); long len = strlen(iname_a); // case 1: odir and rdir are null // action: output the input directory name // if ((odir_a[0] == (char)NULL) && (rdir_a[0] == (char)NULL)) { // if it exists, split the name // else: insert a "./" // if (str != (char*)NULL) { long base_len = strlen(str); memcpy(tdir_a, iname_a, (len - base_len) * sizeof(char)); tdir_a[len - base_len] = (char)NULL; strcpy(tname_a, str + 1); } else { strcpy(tdir_a, Itgl::DOT); strcpy(tname_a, iname_a); } } // case 2: odir is null and rdir is not null // action: find and replace the string // else if ((odir_a[0] == (char)NULL) && (rdir_a[0] != (char)NULL)) { // find the replace string // long rlen = strlen(rdir_a); long newlen = len - rlen - 1; // if no match, just copy the full input name to the output // if (str == (char*)NULL) { strcpy(tdir_a, Itgl::DOT); strcpy(tname_a, iname_a); } // else if there is match: chop up the input name and // only copy the part that doesn't match rdir. be sure // to not copy the leading slash // else if (strncmp(iname_a, rdir_a, rlen) == 0) { strcpy(tdir_a, rdir_a); memmove(tname_a, iname_a + rlen + 1, newlen); tname_a[newlen] = (char)NULL; } // else: split and copy the input to the output // else { long base_len = strlen(str); memcpy(tdir_a, iname_a, (len - base_len) * sizeof(char)); tdir_a[len - base_len] = (char)NULL; strcpy(tname_a, str + 1); } } // case 3: odir is not null and rdir is null // action: copy both odir and iname to the output // be sure to strip a leading slash from iname // else if ((odir_a[0] != (char)NULL) && (rdir_a[0] == (char)NULL)) { strcpy(tdir_a, odir_a); if (iname_a[0] == (char)Itgl::SLASH[0]) { strcpy(tname_a, iname_a + 1); } else { strcpy(tname_a, iname_a); } } // case 4: odir is not null and rdir is not null // action: find and replace the string, always copy odir to tdir // else if ((odir_a[0] != (char)NULL) && (rdir_a[0] != (char)NULL)) { // compute lengths of the replace string and the remaining portion // long rlen = strlen(rdir_a); long olen = strlen(odir_a); long newlen = len - rlen - 1; long oldlen = len - olen - 1; // if rdir exists in the input filename, remove it and replace it with odir // if (strncmp(iname_a, rdir_a, rlen) == 0) { strcpy(tdir_a, odir_a); memmove(tname_a, iname_a + rlen + 1, newlen); tname_a[newlen] = (char)NULL; } // if the input has the same string as odir, replicate it in the output // else if (strncmp(iname_a, odir_a, olen) == 0) { strcpy(tdir_a, odir_a); memmove(tname_a, iname_a + olen + 1, oldlen); tname_a[oldlen] = (char)NULL; } // else: insert odir into tdir // else { strcpy(tdir_a, odir_a); strcpy(tname_a, iname_a); } } // exit gracefully // return true; } // method: create_filename // // arguments: // char* oname: output filename (output) // char* iname: input filename (input) // char* odir: output directory (input) // char* oext: output extension (input) // char* rdir: replace directory (input) // bool cdir: create the directory path (input) // // return: a boolean indicating status // // This method parses a filename and generates a new directory name // and file extension (e.g., ./foo.edf => /data/isip/foo.feat). // The parser is very rigid. Note: // (1) if odir is empty, the new file is put in the same directory // as the input. // bool Edf::create_filename(char* oname_a, const char* iname_a, const char* odir_a, const char* oext_a, const char* rdir_a, bool cdir_a) { // strip any trailing directory delimiters // char odir[Itgl::MAX_MSTR_LENGTH]; strcpy(odir, odir_a); trim_last_character(odir, Itgl::SLASH[0]); char oext[Itgl::MAX_MSTR_LENGTH]; strcpy(oext, oext_a); trim_last_character(oext, Itgl::SLASH[0]); char rdir[Itgl::MAX_MSTR_LENGTH]; strcpy(rdir, rdir_a); trim_last_character(rdir, Itgl::SLASH[0]); // apply the replace directory // char tdir[Itgl::MAX_MSTR_LENGTH]; char tname[Itgl::MAX_MSTR_LENGTH]; trans_filename(tdir, tname, iname_a, odir, rdir); // swap the extension if necessary: // be sure to check if an extension exists // if (oext_a != (char*)NULL) { char* pos = rindex(tname, (char)Itgl::DOT[0]); char* pos_slash = rindex(tname, (char)Itgl::SLASH[0]); if ((pos > pos_slash) && (pos != (char*)NULL)) { strcpy(pos + 1, oext_a); } else { strcat(tname, Itgl::DOT); strcat(tname, oext_a); } } // create the new filename // strcpy(oname_a, tdir); strcat(oname_a, Itgl::SLASH); strcat(oname_a, tname); if (dbgl_d > Dbgl::BRIEF) { fprintf(stdout, "%s (line: %d) %s: input name: [%s]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, iname_a); fprintf(stdout, "%s (line: %d) %s: odir: [%s], oext: [%s], rdir: [%s]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, odir, oext, rdir); fprintf(stdout, "%s (line: %d) %s: tdir: [%s] tname: [%s]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, tdir, tname); fprintf(stdout, "%s (line: %d) %s: new name: [%s]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, oname_a); } // make sure the files are not identical: // we have to do this by checking the full pathname. since the new file // doesn't exist, realpath only returns the directory, so we still have // to construct the output filename. // char istr[Itgl::MAX_MSTR_LENGTH]; char ostr[Itgl::MAX_MSTR_LENGTH]; realpath(iname_a, istr); realpath(oname_a, ostr); strcat(ostr, Itgl::SLASH); strcat(ostr, tname); if (strcmp(istr, ostr) == 0) { fprintf(stdout, "Error: %s (line: %d) %s: %s [i: %s] [i: %s] [o: %s] [o: %s]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, "identical files", istr, iname_a, ostr, oname_a); return false; } // create necessary directories: // note that we have to recompute the full directory path // because tdir[][ might not contain the full directory spec. // part of it might be a part of tname. // if (cdir_a == true) { char ttdir[Itgl::MAX_MSTR_LENGTH]; char* ptr_slash = rindex(oname_a, (char)Itgl::SLASH[0]); long newlen = ptr_slash - oname_a; if (ptr_slash != (char*)NULL) { memcpy(ttdir, oname_a, newlen); ttdir[newlen] = (char)NULL; } else { ttdir[0] = (char)NULL; } if (create_directory(ttdir) == false) { fprintf(stdout, "Error: %s (line: %d) %s: %s %s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, "error creating directory", ttdir); } } // exit gracefully // return true; } // method: create_filelist // // arguments: // char** onames: output filelist (output) // long num_names: the number of names to be created // char* iname: input filename (input) // char* omod: output filename permuter (input) // // return: a boolean indicating status // // This method essentially permutes filenames according to the template // provided in the omod argument. Typically, it creates names of the form: // // foo_ch00.edf // foo_ch01.edf // ... // // This method is used to convert multichannel edf files to htk format. // bool Edf::create_filelist(char** onames_a, long num_names_a, const char* iname_a, const char* omod_a) { // declare local variables // char tmp_buf[Itgl::MAX_LSTR_LENGTH]; char tmp_mod[Itgl::MAX_MSTR_LENGTH]; // find the delimiter // char* delim = rindex((char*)iname_a, Itgl::DOT[0]); // loop over all filenames // for (long i = 0; i < num_names_a; i++) { // copy the first part of the name // strncpy(tmp_buf, iname_a, delim - iname_a); tmp_buf[delim - iname_a] = (char)NULL; // add the modifier // sprintf(tmp_mod, omod_a, i); strcat(tmp_buf, tmp_mod); // add the last part of the name back // strcat(tmp_buf, delim); // create space and copy // onames_a[i] = new char[strlen(tmp_buf) + 1]; strcpy(onames_a[i], tmp_buf); } // exit gracefully // return true; } // method: create_directory // // arguments: // char* path: input path (input) // mode_t mode: permissions for the directories to be created // // return: a boolean indicating status // // This method creates the directories in the input path if the directories do // not exist. // bool Edf::create_directory(const char* path_a, mode_t mode_a) { // const cast for the input path // char* p = const_cast(path_a); // Do mkdir for each slash until end of string or error // while (*p != (char)NULL) { // Skip first character // p++; // Find first slash or end // while(*p != (char)NULL && *p != Itgl::SLASH[0]) p++; // Remember value of the path // char v = *p; // Write end of string at p // *p = (char)NULL; // Create folder from path to the null char inserted at p // if(mkdir(path_a, mode_a) == ERR_FILE && errno != EEXIST) { *p = v; return false; } // Restore path // *p = v; } return true; } // // end of file