inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/parse
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_parse
00005 #define inlib_parse
00006 
00007 // used in OpenPAW and Lib/FunctionManager.
00008 
00009 #include "smanip"
00010 #include "charmanip"
00011 #include "cstr"
00012 
00013 #include <clocale>
00014 
00015 namespace inlib {
00016 
00017 template <class T>
00018 inline bool to_vals_one(const std::string& a_string,std::vector<T>& a_vals){
00019   std::string::size_type pos = a_string.find('*');
00020   if(pos==std::string::npos){
00021     T value;
00022     if(!inlib::to<T>(a_string,value)) return false;
00023     a_vals.push_back(value);
00024   } else {
00025     //3*2.4
00026     //01234
00027     std::string sn = a_string.substr(0,pos);
00028     std::string sv = a_string.substr(pos+1,a_string.size()-(pos+1));
00029     int multiplier;
00030     if(!inlib::to<int>(sn,multiplier)) return false;
00031     T value;
00032     if(!inlib::to<T>(sv,value)) return false;
00033     for(int index=0;index<multiplier;index++) a_vals.push_back(value);
00034   }
00035   return true;
00036 }
00037 
00038 template <class T>
00039 inline bool to_vals(const std::string& a_string,const char a_sep,std::vector<T>& a_vals){
00040   // Support PAW syntax : 3*2.4 is understood as three times 2.4.
00041   a_vals.clear();
00042   if(a_string.empty()) return true;
00043   std::string::size_type lim = 1;
00044   std::string::size_type l = a_string.length();
00045   std::string::size_type pos = 0;
00046   while(true) {
00047     std::string::size_type index = a_string.find(a_sep,pos);
00048     if(index==std::string::npos){ // Last word.
00049       if((l-pos)>=lim) {
00050         if(!to_vals_one<T>(a_string.substr(pos,l-pos),a_vals)) {
00051           a_vals.clear();
00052           return false;
00053         }
00054       }
00055       break;
00056     } else {
00057       //     abcxxxef
00058       //     0  3  67
00059       if((index-pos)>=lim) {
00060         if(!to_vals_one<T>(a_string.substr(pos,index-pos),a_vals)) {
00061           a_vals.clear();
00062           return false;
00063         }
00064       }
00065       pos = index + 1;
00066     }
00067   }
00068   return true;
00069 }
00070 
00071 inline bool name_args( const std::string& a_string,std::string& aName,std::vector<std::string>& aArgs){
00072   // Look if aName is of the form <string>(<string>,...,<string>)
00073   // return true if so.
00074   // return true if <string> without args
00075   // return false if any bad syntax.
00076   std::string::size_type lb = a_string.find('(');
00077   std::string::size_type rb = a_string.rfind(')');
00078   if( (lb==std::string::npos) && (rb==std::string::npos) ) {
00079     aName = a_string;
00080     aArgs.clear();
00081     return true;
00082   } else if( (lb==std::string::npos) && (rb!=std::string::npos) ) {
00083     aName = "";
00084     aArgs.clear();
00085     return false;
00086   } else if( (lb!=std::string::npos) && (rb==std::string::npos) ) {
00087     aName = "";
00088     aArgs.clear();
00089     return false;
00090   } else if(lb>=rb) {
00091     aName = "";
00092     aArgs.clear();
00093     return false;
00094   }
00095   std::string s = a_string.substr(lb+1,rb-lb-1);
00096   inlib::words(s,",",true,aArgs);
00097   aName = a_string.substr(0,lb);
00098   return true; 
00099 }
00100 
00101 inline bool parse_array(const std::string& a_string,std::string& aName,int& aIndex){
00102   // Look if aName is of the form <string>(<integer>)
00103   // return true if <string>(<integer>)
00104   // return true if <string>. aName = <string> and aIndex = NotFound (-1).
00105   // return false if bad syntax or <integer> not an integer.
00106   std::string::size_type lb = a_string.find('(');
00107   std::string::size_type rb = a_string.rfind(')');
00108   if( (lb==std::string::npos) && (rb==std::string::npos) ) {
00109     aName = a_string;
00110     aIndex = (-1);
00111     return true;
00112   } else if( (lb==std::string::npos) && (rb!=std::string::npos) ) {
00113     aName = "";
00114     aIndex = 0;
00115     return false;
00116   } else if( (lb!=std::string::npos) && (rb==std::string::npos) ) {
00117     aName = "";
00118     aIndex = 0;
00119     return false;
00120   } else if(lb>=rb) {
00121     aName = "";
00122     aIndex = 0;
00123     return false;
00124   }
00125   //012345678
00126   //Slash::Core::ILibraryManager(123)
00127   std::string s = a_string.substr(lb+1,rb-lb-1);
00128   if(!inlib::to<int>(s,aIndex)) {
00129     aName = "";
00130     aIndex = 0;
00131     return false;
00132   }
00133   aName = a_string.substr(0,lb);
00134   return true; 
00135 }
00136 
00137 inline bool to_doubles(const std::string& a_string,std::vector<double>& a_values,const std::string& a_sep){
00138   // Support PAW syntax : 3*2.4 is understood as three times 2.4.
00139   a_values.clear();
00140   std::vector<std::string> words;
00141   inlib::words(a_string,a_sep,false,words);
00142   bool seekMultiplier = (a_sep!="*"?true:false);
00143   if(!seekMultiplier) a_values.resize(words.size());
00144   int valuei = 0;
00145   std::vector<std::string> subwords;
00146   std::vector<std::string>::iterator it;
00147   for(it = words.begin();it!=words.end();++it) {
00148     if(seekMultiplier) {
00149       std::string::size_type pos = (*it).find('*');
00150       if(pos==std::string::npos){
00151         double value;
00152         if(!inlib::to<double>(*it,value)) {
00153           a_values.clear();
00154           return false;
00155         }
00156         a_values.push_back(value);
00157       } else {
00158         //3*2.4
00159         //01234
00160         std::string sn = (*it).substr(0,pos);
00161         std::string sv = (*it).substr(pos+1,a_string.size()-(pos+1));
00162         int multiplier;
00163         if(!inlib::to<int>(sn,multiplier)) {
00164           a_values.clear();
00165           return false;
00166         }
00167         double value;
00168         if(!inlib::to<double>(sv,value)) {
00169           a_values.clear();
00170           return false;
00171         }
00172         for(int index=0;index<multiplier;index++) a_values.push_back(value);
00173       }
00174     } else {
00175       double value;
00176       if(!inlib::to<double>(*it,value)) {
00177         a_values.clear();
00178         return false;
00179       }
00180       a_values[valuei] = value;
00181       valuei++;
00182     }    
00183   }
00184   return true;
00185 }
00186 
00187 inline bool is_variable(const std::string& a_string){
00188   // Check if a_string is of the form of a programmation variable.
00189   // - not empty.
00190   // - not starting by a number.
00191   // - being composed of alphanumeric, number and '_' characters.
00192   if(!a_string.size()) return false;
00193   char* pos = (char*)a_string.c_str();
00194   if(inlib::is_digit(*pos)) return false;
00195   pos++;
00196   while(*pos) {
00197     if( !inlib::is_letter(*pos) && 
00198         !inlib::is_digit(*pos) && 
00199         ((*pos)!='_') ) return false;
00200     pos++;
00201   }
00202   return true;
00203 }
00204 
00205 inline unsigned int cstring_strtods(const char* a_cstr,std::vector<double>& a_vals,bool a_fixed = false){
00206   // a_fixed = false : a_vals size is adapted according to what is read.
00207   // a_fixed = true : a_vals size is fixed. If less is read, then the
00208   //                 rest is pad with 0.
00209   // return : the number of double read.
00210 
00211   char* old = str_dup(::setlocale(LC_NUMERIC,0));
00212   ::setlocale(LC_NUMERIC,"C");
00213 
00214   unsigned int n = a_vals.size();
00215   char* begin = (char*)a_cstr;
00216   char* end;
00217   double d;
00218   unsigned int index = 0;
00219   std::vector<double>::iterator it = a_vals.begin();
00220   while(true) {  
00221     d = ::strtod(begin,&end);
00222     if(end==begin) {
00223       if(a_fixed) {
00224         for(;it!=a_vals.end();++it) *it = 0;
00225       } else {
00226         if(index<n) a_vals.resize(index);
00227       }
00228       ::setlocale(LC_NUMERIC,old);
00229       str_del(old);
00230       return index;
00231     }
00232     if(index<n) {
00233       *it = d;
00234       it++;
00235     } else {
00236       if(a_fixed) {
00237         ::setlocale(LC_NUMERIC,old);
00238         str_del(old);
00239         return index;
00240       }
00241       a_vals.push_back(d);
00242     }
00243     index++;
00244     begin = end;
00245   }
00246 }
00247 
00248 }
00249 
00250 #include "file"
00251 #include "vmanip"
00252 
00253 namespace inlib {
00254 
00255 inline bool read_doubles(const std::string& a_file,std::vector<double>& a_vals){
00256   a_vals.clear();
00257   FILE* file = ::fopen(a_file.c_str(),"rb");
00258   if(!file) return false;
00259   unsigned int BUFSIZE = 65536;
00260   char* buffer = new char[BUFSIZE+1];
00261   if(!buffer) {::fclose(file);return false;}
00262   std::string sep = " ";
00263   while(true) {
00264     size_t l;
00265     if(!file::read_cstring(file,buffer,BUFSIZE,l)) break; // EOF.
00266     std::string sbuffer = buffer; //can we avoid this copy ?
00267     std::vector<double> ds;
00268     if(!inlib::to_doubles(sbuffer,ds,sep)) {
00269       a_vals.clear();
00270       delete [] buffer;
00271       ::fclose(file);
00272       return false;
00273     }
00274     inlib::append<double>(a_vals,ds);
00275   }
00276   delete [] buffer;
00277   ::fclose(file);
00278   return true;
00279 }
00280 
00281 }
00282 
00283 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines