cgma
CubitFileUtil.cpp
Go to the documentation of this file.
00001 //- Class:          CubitFileUtil
00002 //- Description:    Class with functions to get files from a directory, etc.
00003 //- Owner:          Steve Storm
00004 
00005 #define NOMINMAX
00006 
00007 #include "CubitFileUtil.hpp"
00008 #include "CubitUtil.hpp"
00009 #include "CubitString.hpp"
00010 #include "CubitMessage.hpp"
00011 #include "CubitDirIterator.hpp"
00012 
00013 #ifdef _WIN32
00014   #include <sys/types.h>
00015   #include <sys/stat.h>
00016   #include <windows.h>
00017   #ifndef PATH_MAX
00018     #define PATH_MAX _MAX_PATH
00019   #endif
00020   #include "shlwapi.h"
00021 #else
00022   #include <sys/types.h>
00023   #include <sys/stat.h>
00024   #include <dirent.h>
00025   #include <cstdlib>
00026   #include <sys/param.h>
00027   #include <unistd.h>
00028   #include <pwd.h>
00029   #include <fnmatch.h>
00030 #endif
00031 #include <errno.h>
00032 #include <string.h>
00033 
00034 #include <algorithm>
00035 
00036 
00037 #ifdef _WIN32
00038 static const char* DIR_SEP_STR = "\\";
00039 static const char DIR_SEP_CHAR = '\\';
00040 #else
00041 static const char* DIR_SEP_STR = "/";
00042 static const char DIR_SEP_CHAR = '/';
00043 #endif
00044    
00045 const char* CubitFileUtil::separator()
00046 {
00047   return DIR_SEP_STR;
00048 }
00049 
00050 CubitStatus
00051 CubitFileUtil::get_current_working_directory( CubitString& wd )
00052 {
00053 #ifdef _WIN32
00054   wchar_t* buffer = _wgetcwd( NULL, 0 );
00055 #else
00056   char* buffer = getcwd( NULL, 0 );
00057 #endif
00058   if (!buffer)
00059   {
00060     PRINT_WARNING( "Unable to get new working directory\n" );
00061     return CUBIT_FAILURE;
00062   }
00063   else
00064   {
00065     // convert to string
00066 #ifdef _WIN32
00067     wd = CubitString::toUtf8(buffer);
00068 #else
00069     wd = buffer;
00070 #endif
00071 
00072     // Add a slash at the end, if not already there
00073     int wd_len = wd.length();
00074     if( wd.c_str()[wd_len-1] != DIR_SEP_CHAR )
00075     {
00076       wd += DIR_SEP_STR;
00077 
00078       free(buffer);
00079     }
00080 
00081 // TODO: need to figure out the right way to do this. This assumes
00082 // variables of length PATH_MAX which is bad!
00083 //#ifdef _WIN32
00084 //    // Make sure format is compatible with full path format
00085 //    CubitString full_path_str;
00086 //    if( get_full_path_str( wd, full_path_str ) == CUBIT_SUCCESS )
00087 //      strcpy( wd, full_path_str.c_str() );
00088 //#endif
00089 
00090     return CUBIT_SUCCESS;
00091   }
00092 }
00093 
00094 CubitStatus CubitFileUtil::set_current_working_directory( const CubitString& wd )
00095 {
00096 #ifdef _WIN32
00097   int ret = _wchdir(CubitString::toUtf16(wd).c_str());
00098 #else
00099   int ret = chdir(wd.c_str());
00100 #endif
00101   return ret == 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
00102 }
00103 
00104 CubitString CubitFileUtil::add_name_to_path( const CubitString& path, const CubitString& name )
00105 {
00106   CubitString result = path;
00107   // Add a slash at the end of the path, if not already there
00108   int path_len = result.length();
00109   if( result.c_str()[path_len-1] != DIR_SEP_CHAR )
00110   {
00111     result += DIR_SEP_STR;
00112   }
00113   // append the name to the end of the path
00114   result += name;
00115       
00116   return result;
00117 }
00118 
00119 CubitString CubitFileUtil::find_home_path(const CubitString& which_user)
00120 {
00121   CubitString home_dir;
00122 
00123 #ifdef _WIN32
00124   home_dir = CubitUtil::getenv("USERPROFILE");
00125 #else
00126   if(which_user.length() == 0)
00127   {
00128     home_dir = CubitUtil::getenv("HOME");
00129     if( home_dir.length() == 0 )
00130     {
00131       struct passwd* userdata = getpwuid( getuid() );
00132       if( userdata )
00133         home_dir = userdata->pw_dir;
00134     }
00135   }
00136   else
00137   {
00138     struct passwd* userdata = getpwnam( which_user.c_str() );
00139     if(userdata)
00140       home_dir = userdata->pw_dir;
00141   }
00142 #endif
00143 
00144   return home_dir;
00145 }
00146 
00147 CubitStatus
00148 CubitFileUtil::create_directory( const CubitString& wd )
00149 {
00150   // Create the directory
00151 #ifdef _WIN32
00152   if (_wmkdir(CubitString::toUtf16(wd).c_str()) == -1)
00153   {  
00154     PRINT_WARNING( "Unable to create new directory\n" );
00155     return CUBIT_FAILURE;
00156   }
00157 #else    
00158   if (mkdir(wd.c_str(), 0777) == -1)
00159   {  
00160     PRINT_WARNING( "Unable to create new directory\n" );
00161     return CUBIT_FAILURE;
00162   }
00163 #endif    
00164   return CUBIT_SUCCESS;
00165 }
00166 
00167 
00168 CubitStatus CubitFileUtil::remove_file( const CubitString& file )
00169 {
00170 #ifdef _WIN32
00171   int status = _wremove(CubitString::toUtf16(file).c_str());
00172 #else
00173   int status = remove(file.c_str());
00174 #endif
00175   return status == 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
00176 }
00177 
00178 CubitStatus CubitFileUtil::rename_file( const CubitString& old_file, const CubitString& new_file )
00179 {
00180 #ifdef _WIN32
00181   int status = _wrename(CubitString::toUtf16(old_file).c_str(), CubitString::toUtf16(new_file).c_str());
00182 #else
00183   int status = rename(old_file.c_str(), new_file.c_str());
00184 #endif
00185   return status == 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
00186 }
00187 
00188 CubitStatus
00189 CubitFileUtil::get_full_path_str( const CubitString& part,
00190                                   CubitString &full_path_str )
00191 {
00192   CubitString my_part = CubitFileUtil::make_path_platform_compatible(part);
00193 
00194 #ifdef _WIN32
00195 
00196   wchar_t* full = _wfullpath(NULL, CubitString::toUtf16(my_part).c_str(), 0);
00197   if(!full)
00198   {
00199     PRINT_ERROR( "problem getting full path to %s\n", part.c_str() );
00200     return CUBIT_FAILURE;
00201   }
00202   full_path_str = CubitString::toUtf8(full);
00203   free(full);
00204   
00205 #else
00206 
00207   // we loop removing parts until realpath can resolve an existing path,
00208   // then add the non-existing parts back on.
00209 
00210   std::vector<CubitString> split_parts;
00211   CubitString trypart = part;
00212 
00213   if(!CubitFileUtil::is_absolute(trypart))
00214   {
00215     CubitString cwd;
00216     CubitFileUtil::get_current_working_directory(cwd);
00217     trypart = CubitFileUtil::add_name_to_path(cwd, trypart);
00218   }
00219 
00220   char full[PATH_MAX];
00221   while(trypart.length() && !realpath(trypart.c_str(), full))
00222   {
00223     CubitString split_part1, split_part2;
00224     CubitFileUtil::split_path(trypart, split_part1, split_part2);
00225     split_parts.push_back(split_part2);
00226     if(split_part1.length() == 0)
00227     {
00228       PRINT_ERROR( "problem getting full path to %s\n", part.c_str() );
00229       return CUBIT_FAILURE;
00230     }
00231     trypart = split_part1;
00232   }
00233 
00234   full_path_str = full;
00235   for(size_t i=0; i<split_parts.size(); i++)
00236   {
00237     full_path_str += CubitString("/") + split_parts[split_parts.size() - i - 1];
00238   }
00239 
00240 #endif
00241 
00242   return CUBIT_SUCCESS;
00243 }
00244 
00245 CubitString
00246 CubitFileUtil::make_path_platform_compatible( const CubitString& path)
00247 {
00248   CubitString ret = path;
00249   for(size_t i=0; i<ret.length(); i++)
00250   {
00251 #ifdef _WIN32
00252   // Replace '/' with '\\'
00253     if(ret.get_at(i) == '/' )
00254       ret.put_at(i, '\\');
00255 #else
00256      // Replace '\\' with '/'
00257     if(ret.get_at(i) == '\\' )
00258       ret.put_at(i, '/');
00259 #endif
00260   }
00261   return ret;
00262 }
00263 
00264 CubitString
00265 CubitFileUtil::get_nice_filename( const CubitString& path )
00266 {
00267   CubitString ret_str;
00268 
00269   CubitString dpart_in, fpart_in;
00270   split_path( path, dpart_in, fpart_in );
00271 
00272   CubitString wd;
00273   get_current_working_directory( wd );
00274 
00275   if( dpart_in == wd )
00276     ret_str = fpart_in;
00277   else
00278     ret_str = path;
00279 
00280   return ret_str;
00281 }
00282 
00283 void
00284 CubitFileUtil::split_path( const CubitString& path, CubitString& dirpart, CubitString& filepart )
00285 {
00286   CubitString mypath = path;
00287   while(mypath.length() && mypath.get_at(mypath.length()-1) == DIR_SEP_CHAR)
00288   {
00289     mypath = mypath.substr(0, mypath.length()-1);
00290   }
00291   size_t pos = mypath.find_last(DIR_SEP_CHAR);
00292 
00293   // No separator - could be filename or directory.  We assume
00294   // it's a directory.
00295   if(pos == CubitString::npos)
00296   {
00297     filepart = ".";
00298     dirpart = mypath;
00299   }
00300   else
00301   {
00302     filepart = mypath.substr(pos+1);
00303     dirpart = mypath.substr(0, pos);
00304   }
00305 
00306   // Add slash on end of dirpart if not already there
00307   if(dirpart.length() && dirpart.get_at(dirpart.length()-1) != DIR_SEP_CHAR)
00308     dirpart += DIR_SEP_STR;
00309 
00310   return;
00311 }
00312 
00313 
00314 CubitString
00315 CubitFileUtil::get_file_extension(
00316   const CubitString& file,
00317   bool remove_version /* remove .1, .2, ...*/ )
00318 {
00319   size_t dot_pos = file.find_last('.');
00320   size_t dot_pos2 = 0;
00321 
00322   if ( dot_pos == CubitString::npos )
00323     return "";
00324 
00325   if(remove_version)
00326   {
00327       dot_pos2 = file.find_last('.',dot_pos);
00328     if ( dot_pos2 == CubitString::npos )
00329           remove_version = false;
00330       else if(!is_int_number( file.substr(dot_pos+1).c_str() ))
00331           remove_version = false;
00332   }
00333 
00334   CubitString extension;
00335   if(!remove_version)
00336       extension = file.substr(dot_pos);
00337   else
00338       extension = file.substr(dot_pos2,dot_pos-dot_pos2);
00339   
00340   for ( size_t i = 0; i < extension.length(); i++ )
00341     extension.put_at(i, tolower( extension.get_at(i) ) );
00342     
00343   return extension;
00344   
00345 }  //  get_file_extension()
00346                      
00347 CubitBoolean 
00348 CubitFileUtil::all_chars_are( char ch, const char *str )
00349 {
00350   while( *str )
00351     if( *str++ != ch )
00352       return CUBIT_FALSE;
00353     return CUBIT_TRUE;
00354 }
00355 
00356 CubitBoolean 
00357 CubitFileUtil::is_int_number( const char *str )
00358 {
00359   while( *str )
00360     if( !isdigit(*str++) )
00361       return CUBIT_FALSE;
00362     return CUBIT_TRUE;
00363 }
00364 
00365 CubitBoolean 
00366 CubitFileUtil::contains_char( char ch, const char *str )
00367 {
00368   while( *str )
00369     if( *str++ == ch )
00370       return CUBIT_TRUE;
00371     return CUBIT_FALSE;
00372 }
00373 
00374 //CubitString
00375 //CubitFileUtil::get_default_cubit_file_name()
00376 //{
00377 //  // Get a list of all files matching 'cubit*.cub', in current directory
00378 
00379 //  CubitDirIterator dir_iter(".", "cubit*.cub");
00380 
00381 //  int max_number = 0;
00382 
00383 //  while(dir_iter.has_next())
00384 //  {
00385 //    CubitString f = dir_iter.next();
00386 
00387 //    // cut off the "cubit" at the start and the ".cub" at the end
00388 //    f = f.substr(5, f.length()-9);
00389 //    if( is_int_number(f.c_str()) )
00390 //    {
00391 //      int num = atoi(f.c_str());
00392 //      max_number = std::max(num, max_number);
00393 //    }
00394 //  }
00395 
00396 //  max_number++;
00397 
00398 //  CubitString num_str = CubitString::number(max_number);
00399 //  if(max_number < 10)
00400 //    num_str = CubitString("0") + num_str;
00401 
00402 //  return CubitString("cubit") + num_str + CubitString(".cub");
00403 //}
00404 
00405 int
00406 CubitFileUtil::get_next_filenumber( const CubitString& file_pattern,
00407                                     int &num_matches,
00408                                     int &first_id )
00409 {
00410   // TODO: check this bug?
00411   // Continue if nothing after dot.  Also, I noticed the _WIN32 will match
00412   // file.cub against wildcard file.cub.*
00413 
00414   int max_number = 0;
00415   int min_number = CUBIT_INT_MAX;
00416   num_matches = 0;
00417 
00418   // get directory and file parts
00419   CubitString dir, file, full_file_pattern;
00420   CubitFileUtil::get_full_path_str(file_pattern, full_file_pattern);
00421   CubitFileUtil::split_path(full_file_pattern, dir, file);
00422 
00423   size_t wildcard_location = file.find("*");
00424   if(wildcard_location == CubitString::npos)
00425     return 1;
00426 
00427   CubitDirIterator dir_iter(dir, file);
00428 
00429   while(dir_iter.has_next())
00430   {
00431     CubitString f = dir_iter.next();
00432 
00433     // cut off the matched part
00434     f = f.substr(wildcard_location, 1 + f.length() - file.length());
00435     if( is_int_number(f.c_str()) )
00436     {
00437       int num = atoi(f.c_str());
00438       max_number = std::max(num, max_number);
00439       min_number = std::min(num, min_number);
00440     }
00441     num_matches++;
00442   }
00443 
00444   if( min_number != CUBIT_INT_MAX )
00445     first_id = min_number;
00446 
00447   return max_number+1;
00448 }
00449 
00450 bool CubitFileUtil::is_directory(const CubitString& path)
00451 {
00452   off_t size;
00453   time_t time;
00454   int mode = 0;
00455   if(0 == file_info(path, size, time, mode))
00456   {
00457 #ifdef _WIN32
00458   if( (_S_IFDIR & mode) )
00459 #else
00460   if( S_ISDIR( mode ) )
00461 #endif
00462     {
00463       return true;
00464     }
00465   }
00466   return false;
00467 }
00468 
00469 bool CubitFileUtil::path_exists(const CubitString& path)
00470 {
00471   off_t size;
00472   time_t time;
00473   int mode;
00474   return 0 == file_info(path, size, time, mode);
00475 }
00476    
00477 bool CubitFileUtil::is_absolute(const CubitString& path)
00478 {
00479 #ifdef _WIN32
00480   return !PathIsRelativeW(CubitString::toUtf16(path).c_str());
00481 #else
00482   return path.c_str()[0] == '/' ? true : false;
00483 #endif
00484 }
00485    
00486 int  CubitFileUtil::file_info(const CubitString& path, off_t& size, time_t& time, int& mode)
00487 {
00488 #ifdef _WIN32
00489   // remove trailing separators
00490   CubitString mypath = path;
00491   if(mypath.length() >= 1 && mypath.get_at(mypath.length()-1) == DIR_SEP_CHAR)
00492     mypath = mypath.substr(0, mypath.length()-1);
00493   struct _stati64 file_info;
00494   int stat_result = _wstati64( CubitString::toUtf16(mypath).c_str(), &file_info );
00495 #else
00496   struct stat file_info;
00497   int stat_result = lstat( path.c_str(), &file_info );
00498 #endif
00499 
00500   if(stat_result == 0)
00501   {
00502     size = file_info.st_size;
00503     time = file_info.st_mtime;
00504     mode = file_info.st_mode;
00505     return 0;
00506   }
00507   return errno ? errno : ENOENT;
00508 }
00509 
00510 int CubitFileUtil::complete_filename(CubitString& line, int& num_additional_chars, bool& found_quote)
00511 {
00512   // save the original length
00513   num_additional_chars = line.length();
00514   char* buffer = (char*) line.c_str();
00515 
00516   char *ptr_from;
00517   if ( (ptr_from = strrchr(buffer, '\'')) == NULL &&
00518        (ptr_from = strrchr(buffer, '\"')) == NULL)
00519   {
00520     return -1;
00521   }
00522   
00523   ptr_from++; // skip past the single/double quote
00524   
00525     // Separate the directory portion from the filename portion (if any)
00526   char *file;
00527   char *path;
00528 
00529 #ifndef _WIN32
00530   if ((file = strrchr(ptr_from, '/')) == NULL) // No path
00531   {
00532     path = strdup(".");
00533     file = strdup(ptr_from);
00534   }
00535   else if (file == ptr_from)
00536   {
00537     path = strdup("/");
00538     file = strdup(ptr_from + 1);
00539   }
00540   else
00541   {
00542     path = strdup(ptr_from);
00543     char *end = strrchr(path, '/');
00544     *end = '\0';
00545     ++file;
00546     file = strdup(file);
00547 
00548     if ( *path == '~' )
00549     {
00550       const char *home = getenv("HOME");
00551       if( !home )
00552       {
00553         struct passwd* userdata = getpwuid( getuid() );
00554         if( userdata )
00555           home = userdata->pw_dir;
00556       }
00557       char *after_tilde = path;
00558       after_tilde++;
00559       std::string new_path = home;
00560       new_path += after_tilde;
00561       free(path);
00562       path = strdup( new_path.c_str() );
00563     }
00564 
00565   }
00566 #else
00567   file = strrchr(ptr_from, '\\');
00568   bool slash = 0;
00569   if(file == NULL)
00570   {
00571     slash = 1;
00572     file = strrchr(ptr_from, '/');
00573   }
00574   if(file == NULL)
00575 //   if ((file = strrchr(ptr_from, '\\')) == NULL
00576 //       && file = strrchr(ptr_from, '/') == NULL) // No path
00577   {
00578     path = strdup(".");
00579     file = strdup(ptr_from);
00580   }
00581   else if (file == ptr_from)
00582   {
00583     path = strdup("\\");
00584     file = strdup(ptr_from + 1);
00585   }
00586   else
00587   {
00588     path = strdup(ptr_from);
00589     char *end;
00590     if(slash)
00591        end = strrchr(path, '/');
00592     else
00593        end = strrchr(path, '\\');
00594     
00595     *end = '\0';
00596     ++file;
00597     file = strdup(file);
00598   }
00599 #endif  
00600     // Determine what type of files to match (suffix_strings)
00601     // Need to lowercase keyword and identifier.....
00602   char *tmp_str = strdup(buffer);
00603   char *keyword = strtok(tmp_str, " \t");
00604   CubitUtil::convert_string_to_lowercase(keyword);
00605   int lenkey = strlen(keyword);
00606   std::vector<std::string> suffix_strings;
00607   
00608   if ((strncmp("import", keyword, lenkey) == 0) ||
00609       (strncmp("export", keyword, lenkey) == 0))
00610   {
00611     char *identifier = strtok(NULL, " \t");
00612     CubitUtil::convert_string_to_lowercase(identifier);
00613     int lenid  = strlen(identifier);
00614 
00615       //Let's set up a vector of strings
00616     std::vector<std::string> acis_strings, cubfile_strings,iges_strings,
00617        catia_strings,proe_strings,step_strings,fastq_strings, mesh_strings,
00618         facet_strings, avs_strings, stl_strings, ideas_strings, abaqus_strings,
00619         nastran_strings, presto_strings;
00620 
00621     iges_strings.push_back(".igs");
00622     iges_strings.push_back(".iges");
00623 
00624 
00625 #ifdef GRANITE  
00626     proe_strings.push_back(".prt");
00627     proe_strings.push_back(".asm");
00628     proe_strings.push_back(".prt.");
00629     proe_strings.push_back(".asm.");
00630     proe_strings.push_back(".g");
00631 #endif  
00632 #ifdef CATIA
00633     catia_strings.push_back(".catpart");
00634     catia_strings.push_back(".catproduct");
00635     catia_strings.push_back(".ncgm");    
00636 #endif  
00637 
00638     step_strings.push_back(".stp");
00639     step_strings.push_back(".step");
00640 
00641     fastq_strings.push_back(".fsq");
00642 
00643     mesh_strings.push_back(".g");
00644     mesh_strings.push_back(".e");
00645     mesh_strings.push_back(".exo");
00646     mesh_strings.push_back(".exoII");
00647     mesh_strings.push_back(".gen");
00648 
00649     facet_strings.push_back(".facets");
00650     facet_strings.push_back(".facet");
00651     facet_strings.push_back(".fac");
00652     facet_strings.push_back(".off");
00653     facet_strings.push_back(".OFF");
00654     
00655     avs_strings.push_back(".avs");
00656 
00657     stl_strings.push_back(".stl");
00658 
00659     ideas_strings.push_back(".unv");
00660 
00661     abaqus_strings.push_back(".inp");
00662 
00663     nastran_strings.push_back(".bdf");
00664 
00665     presto_strings.push_back(".i");
00666     
00667     if (strncmp("iges", identifier, lenid) == 0)
00668     {
00669       suffix_strings.assign(iges_strings.begin(), iges_strings.end());
00670     }
00671     
00672 
00673 #ifdef CATIA
00674     else if (strncmp("catia", identifier, lenid) == 0)
00675     {
00676       suffix_strings.assign(catia_strings.begin(), catia_strings.end());
00677     }
00678 #endif
00679 
00680 #ifdef GRANITE  
00681     else if (strncmp("proe", identifier, lenid) == 0)
00682     {
00683       suffix_strings.assign(proe_strings.begin(), proe_strings.end());
00684     }
00685 #endif  
00686      else if (strncmp("step", identifier, lenid) == 0)
00687     {
00688       suffix_strings.assign(step_strings.begin(), step_strings.end());
00689     }
00690     else if (strncmp("fastq", identifier, lenid) == 0)
00691     {
00692       suffix_strings.assign(fastq_strings.begin(), fastq_strings.end());
00693     }
00694     else if ( strncmp("mesh", identifier, lenid) == 0 ||
00695               strncmp("free", identifier, lenid) == 0 )
00696     {
00697       suffix_strings.assign(mesh_strings.begin(), mesh_strings.end());
00698     }
00699     else if (strncmp("facets", identifier, lenid) == 0)
00700     {
00701       suffix_strings.assign(facet_strings.begin(), facet_strings.end());
00702     }
00703     else if (strncmp("avs", identifier, lenid) == 0)
00704     {
00705       suffix_strings.assign(avs_strings.begin(), avs_strings.end());
00706     }
00707     else if (strncmp("stl", identifier, lenid) == 0)
00708     {
00709       suffix_strings.assign(stl_strings.begin(), stl_strings.end());
00710     }
00711     else if (strncmp("ideas", identifier, lenid) == 0)
00712     {
00713       suffix_strings.assign(ideas_strings.begin(), ideas_strings.end());
00714     }
00715     else if (strncmp("abaqus", identifier, lenid) == 0)
00716     {
00717       suffix_strings.assign(abaqus_strings.begin(), abaqus_strings.end());
00718     }
00719     else if (strncmp("nastran", identifier, lenid) == 0)
00720     {
00721       suffix_strings.assign(nastran_strings.begin(), nastran_strings.end());
00722     }
00723     else if (strncmp("presto", identifier, lenid) == 0)
00724     {
00725       suffix_strings.assign(presto_strings.begin(), presto_strings.end());
00726     }
00727     else //user didn't specify anything, so let's add them all
00728     {
00729       suffix_strings.assign(acis_strings.begin(),acis_strings.end());
00730       suffix_strings.insert(suffix_strings.end(),cubfile_strings.begin(), cubfile_strings.end());
00731       suffix_strings.insert(suffix_strings.end(),iges_strings.begin(), iges_strings.end());
00732 
00733 
00734 #ifdef CATIA
00735       suffix_strings.insert(suffix_strings.end(),catia_strings.begin(), catia_strings.end());
00736 #endif 
00737 
00738 #ifdef GRANITE  
00739       suffix_strings.insert(suffix_strings.end(),proe_strings.begin(), proe_strings.end());
00740 #endif  
00741       suffix_strings.insert(suffix_strings.end(),step_strings.begin(), step_strings.end());
00742       suffix_strings.insert(suffix_strings.end(),fastq_strings.begin(), fastq_strings.end());
00743       suffix_strings.insert(suffix_strings.end(),mesh_strings.begin(), mesh_strings.end());
00744       suffix_strings.insert(suffix_strings.end(),facet_strings.begin(), facet_strings.end());
00745       suffix_strings.insert(suffix_strings.end(),avs_strings.begin(), avs_strings.end());
00746       suffix_strings.insert(suffix_strings.end(),stl_strings.begin(), stl_strings.end());
00747       suffix_strings.insert(suffix_strings.end(),ideas_strings.begin(), ideas_strings.end());
00748       suffix_strings.insert(suffix_strings.end(),abaqus_strings.begin(), abaqus_strings.end());
00749       suffix_strings.insert(suffix_strings.end(),nastran_strings.begin(), nastran_strings.end());
00750     }
00751   }
00752   else if (strncmp("open", keyword, lenkey) == 0)
00753   {
00754     suffix_strings.push_back(".cub");  // Not an actual suffix, just an indicator
00755   }
00756   else if (strncmp("playback", keyword, lenkey) == 0 ||
00757            strncmp("record", keyword, lenkey) == 0)
00758   {
00759     suffix_strings.push_back(".jou");
00760     suffix_strings.push_back(".test");
00761     suffix_strings.push_back(".cubit");
00762   }
00763   else if (strncmp("hardcopy", keyword, lenkey) == 0)
00764   {
00765     suffix_strings.push_back(".ps");
00766   }
00767   else if (strncmp("cd", keyword, lenkey) == 0)
00768   {
00769     suffix_strings.push_back("/");  // Not an actual suffix, just an indicator
00770   }
00771   else
00772   {
00773     suffix_strings.push_back("\0");
00774   }
00775     
00776   free(tmp_str);
00777   
00778   CubitString tmp_line(buffer);
00779   CubitString match = CubitFileUtil::list_matching_files(path, file, suffix_strings, tmp_line);
00780   
00781   if (match.length())
00782   {
00783     int file_length = strlen(file);
00784     match = match.c_str() + file_length;
00785     tmp_line += match;
00786     if (tmp_line.find("\'") != CubitString::npos)
00787         tmp_line += "\'";
00788     else if (tmp_line.find("\"") != CubitString::npos)
00789       tmp_line += "\" ";
00790     else
00791     {
00792       PRINT_ERROR("INTERNAL ERROR: CubitFileUtil::complete_file -- Could not find "
00793                   "quote type.");
00794       tmp_line += "\' ";
00795     }
00796     //gl_in_quoted_string = !gl_in_quoted_string;
00797     //gl_fixup(gl_pos, gl_pos+additional_char);
00798     found_quote = !found_quote;
00799   }
00800   line = tmp_line;
00801   free(path);
00802   free(file);
00803   //gl_redraw();
00804   num_additional_chars = line.length() - num_additional_chars;
00805   
00806   return 1;
00807 }
00808 
00809 CubitString CubitFileUtil::list_matching_files(const char *path, const char *file, std::vector<std::string> suffixes, CubitString& line)
00810 {
00811   CubitString filename;
00812   size_t      len;
00813   int         match = 0;
00814   int         width = 0;
00815   CubitString match_file;
00816   CubitString char_match;
00817   CubitBoolean list_files = CUBIT_FALSE;
00818   CubitBoolean dir_only = CUBIT_FALSE;
00819   CubitBoolean is_dir = CUBIT_FALSE;
00820 
00821   CubitDirIterator dirp(path);
00822 
00823   if (!dirp.has_next())
00824   {
00825     PRINT_INFO("\n");
00826     PRINT_ERROR("Invalid Directory: '%s'\n",
00827                 path);
00828     return "";
00829   }
00830 
00831     // If we're looking for directories only, indicate it
00832   if (suffixes.size() > 0 && suffixes.front() ==  "/")
00833   {
00834     dir_only = CUBIT_TRUE;
00835   }
00836   
00837   len = strlen(file);
00838   while (dirp.has_next())
00839   {
00840     filename = dirp.next();
00841 
00842     // Skip the . and .. entries in the directory
00843     if (filename.c_str()[0] == '.' &&
00844         (filename.c_str()[1] == '\0'))
00845       continue;
00846       // Skip files if we only want directories
00847 
00848     is_dir = CubitFileUtil::is_directory(CubitFileUtil::add_name_to_path(path, filename));
00849         
00850     if (dir_only && !is_dir)
00851        continue;
00852 
00853       // Skip what doesn't match
00854     if (len && strncmp(filename.c_str(), file, len) != 0)
00855       continue;
00856     
00857       // We have a match, see if the suffix (if any) matches
00858     int sat_number_found = 0;
00859 
00860       // Only match ".prt.", or ".asm." if they are followed by just digits.
00861     std::vector<std::string>::iterator suff;
00862     for(suff = suffixes.begin(); suff != suffixes.end(); suff++)
00863     {
00864       
00865       if(*suff == ".prt." ||  *suff == ".asm.")
00866       {        
00867         const char* c_ptr = strstr(filename.c_str(), suff->c_str());
00868         if(c_ptr)
00869         {
00870           c_ptr += 5;
00871             // Make sure the rest of the filename is just digits
00872           sat_number_found = 1;
00873           while(*c_ptr != '\0')
00874           {
00875             if (!isdigit(*c_ptr))
00876                sat_number_found = 0;
00877             c_ptr++;
00878           }
00879         }
00880       }
00881     }
00882     
00883     int found = 0;
00884     const char* dot = strrchr(filename.c_str(), '.');
00885     if(dot != NULL && !is_dir)
00886     {
00887       for(suff = suffixes.begin(); suff != suffixes.end(); suff++)
00888       {
00889 #ifdef _WIN32
00890         if(stricmp(suff->c_str(), dot) == 0)
00891 #else
00892         if(strcasecmp(suff->c_str(), dot) == 0)
00893 #endif
00894         {
00895           found = 1;  //if the suffix matches
00896           break;
00897         }
00898       }
00899     }
00900     else  //If the filename has no suffix, then we'll add it
00901        found = 1;
00902             
00903       
00904     if(suffixes.begin()->size() == 0 || // If no suffix was sent in
00905         found == 1 || //or suffix matches or the filename has no suffix
00906         sat_number_found == 1)  //or if the suffix is something like ".sat."
00907     {
00908         // Save the filename of the first match
00909       if (++match == 1)
00910       {
00911         match_file = filename;
00912         if (list_files == CUBIT_FALSE)
00913           char_match = filename.c_str()+len;
00914       }
00915         // list_files is FALSE until we have found 2 or more matches
00916         // that have no initial characters in common
00917       else if (list_files == CUBIT_FALSE)
00918       {
00919           // If the initial character doesn't match, list instead.
00920         if (char_match.c_str()[0] != filename.c_str()[len])
00921         {
00922             // Indicate that we are listing
00923           list_files = CUBIT_TRUE;
00924             // Indicate that we are starting over
00925           dirp.open(path);
00926           match = 0;
00927             // Undo what has already been done
00928           continue;
00929         }
00930         
00931           // If there is a match, see how many characters match.
00932         for (unsigned int i = 0; i < char_match.length(); i++)
00933         {
00934           if (char_match.c_str()[i] != filename.c_str()[i+len])
00935           {
00936               // Chop off end of char_match
00937             char_match.put_at(i, '\0');
00938             break;
00939           }
00940         }
00941       }
00942         // If two or more matches, we want to 
00943         // output a list, so put out header and first two matches.
00944       else if (match == 2)
00945       {
00946         width = match_file.length() + filename.length() + 6;
00947           // See if we need to add a '/' to the first name
00948         char first_str[2];
00949         first_str[0] = first_str[1] = '\0';
00950         if(CubitFileUtil::is_directory(CubitFileUtil::add_name_to_path(path, match_file)))
00951           first_str[0] = '/';
00952         
00953           // Get ready to test second file
00954         bool tmp_is_dir = CubitFileUtil::is_directory(CubitFileUtil::add_name_to_path(path, filename));
00955 
00956         PRINT_INFO("\n\nPossible filename matches:\n  %s%s  %s%s",
00957                    match_file.c_str(), first_str, filename.c_str(),
00958                    tmp_is_dir ? "/" : "");
00959       }
00960       else  // This is at least the third match, and we
00961           // need to list the file names
00962       {
00963         bool tmp_is_dir = CubitFileUtil::is_directory(CubitFileUtil::add_name_to_path(path, filename));
00964         int dir_adjust = tmp_is_dir ? 1 : 0;
00965         width += filename.length() + 2 + dir_adjust;
00966         if (width > 79)
00967         {
00968           PRINT_INFO(" \n" );
00969           width = filename.length() + 2 + dir_adjust;
00970         }
00971         PRINT_INFO("  %s%s",  filename.c_str(),
00972                    dir_adjust ? "/" : "");
00973       }
00974     }
00975   }
00976 
00977   if (match == 1)
00978   {
00979       // See if match_file is a directory
00980 
00981     if(CubitFileUtil::is_directory(CubitFileUtil::add_name_to_path(path, match_file)))
00982     {
00983         // If our only match is a directory,
00984         // Add the directory name to the buffer, but
00985         // return NULL.
00986         // Otherwise, return match_file.
00987       
00988       // Look at 'line'. Find the first occurance of a '\'. Use that as
00989       // the suffix for the line if found. Otherwise use '/'.
00990 
00991       CubitString suffix = "/";
00992       if (line.find_first('\\') != CubitString::npos)
00993         suffix = "\\";
00994 
00995       line += match_file.substr(len) + suffix;
00996 
00997       match_file = "";
00998     }
00999   }
01000   else if (match > 1)
01001   {
01002       // If we didn't list files,
01003       // add the common chars to the buffer
01004     if (!list_files)
01005       line += char_match;
01006     PRINT_INFO(" \n"  );
01007     match_file = "";
01008   }
01009   
01010   // Return the file name.
01011   // If it was a directory or there was more than one match, it returns an empty string.
01012   return match_file;
01013 }
01014 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines