inlib
1.2.0
|
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