/**************************************************************************/ /* File: flags.cpp */ /* Author: Joachim Schoeberl */ /* Date: 10. Oct. 96 */ /**************************************************************************/ #include "flags.hpp" #ifdef WIN32 #include #endif #include namespace ngcore { using std::string; using std::endl; Flags :: Flags () { ; } Flags :: Flags (const Flags & flags) { string name; for (int i = 0; i < flags.GetNStringFlags(); i++) { string str = flags.GetStringFlag (i, name); SetFlag (name, str); } for (int i = 0; i < flags.GetNNumFlags(); i++) { double val = flags.GetNumFlag (i, name); SetFlag (name, val); } for (int i = 0; i < flags.GetNDefineFlags(); i++) { bool val = flags.GetDefineFlag (i, name); SetFlag (name, val); } for (int i = 0; i < flags.GetNNumListFlags(); i++) { auto numa = flags.GetNumListFlag (i, name); SetFlag (name, *numa); } for (int i = 0; i < flags.GetNStringListFlags(); i++) { auto stra = flags.GetStringListFlag (i, name); SetFlag (name, *stra); } for (int i = 0; i < flags.GetNFlagsFlags(); i++) { auto lflags = flags.GetFlagsFlag (i, name); SetFlag (name, lflags); } for(auto i : Range(flags.anyflags.Size())) { SetFlag(flags.anyflags.GetName(i), flags.anyflags[i]); } } Flags :: Flags (Flags && flags) : strflags(flags.strflags), numflags(flags.numflags), defflags(flags.defflags), strlistflags(flags.strlistflags), numlistflags(flags.numlistflags) { ; } Flags :: Flags (std::initializer_list list) { for (auto i = list.begin(); i < list.end(); i++) SetCommandLineFlag ((string("-")+*i).c_str()); } Flags :: Flags (string f1, string f2, string f3, string f4, string f5) { SetCommandLineFlag ((string("-")+f1).c_str()); if (f2.length()) SetCommandLineFlag ( (string("-")+f2).c_str() ); if (f3.length()) SetCommandLineFlag ( (string("-")+f3).c_str() ); if (f4.length()) SetCommandLineFlag ( (string("-")+f4).c_str() ); if (f5.length()) SetCommandLineFlag ( (string("-")+f5).c_str() ); } Flags :: ~Flags () { DeleteFlags (); } void Flags :: DeleteFlags () { strflags.DeleteAll(); numflags.DeleteAll(); defflags.DeleteAll(); strlistflags.DeleteAll(); numlistflags.DeleteAll(); } Flags Flags :: SetFlag (const char * name, bool b) && { this -> SetFlag (name, b); return std::move(*this); } Flags Flags :: SetFlag (const char * name, double val) && { this -> SetFlag (name, val); return std::move(*this); } Flags & Flags :: SetFlag (const char * name, const string & val) { strflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const char * name, double val) & { numflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const char * name, bool b) & { defflags.Set (name, b); return *this; } Flags & Flags :: SetFlag (const char * name, Flags & val) & { flaglistflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const string & name, const string & val) { // char * hval = new char[strlen (val) + 1]; // strcpy (hval, val); strflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const string & name, double val) { numflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const string & name, bool b) { defflags.Set (name, b); return *this; } Flags & Flags :: SetFlag (const string & name, Flags & val) { flaglistflags.Set (name, val); return *this; } Flags & Flags :: SetFlag (const string & name, const Array & val) { auto strarray = std::make_shared>(val); /* for (int i = 0; i < val.Size(); i++) { strarray->Append (new char[strlen(val[i])+1]); strcpy (strarray->Last(), val[i]); } */ strlistflags.Set (name, strarray); return *this; } Flags & Flags :: SetFlag (const string & name, const Array & val) { // Array * numarray = new Array(val); auto numarray = std::make_shared> (val); numlistflags.Set (name, numarray); return *this; } Flags & Flags :: SetFlag (const string & name, const std::any & val) { anyflags.Set(name, val); return *this; } string Flags :: GetStringFlag (const string & name, const char * def) const { if (strflags.Used (name)) return strflags[name]; else { if (!def) return string(""); return def; } } string Flags :: GetStringFlag (const string & name, string def) const { if (strflags.Used (name)) return strflags[name]; else return def; } double Flags :: GetNumFlag (const string & name, double def) const { if (numflags.Used (name)) return numflags[name]; else return def; } const double * Flags :: GetNumFlagPtr (const string & name) const { if (numflags.Used (name)) return & ((SymbolTable&)numflags)[name]; else return NULL; } double * Flags :: GetNumFlagPtr (const string & name) { if (numflags.Used (name)) return & ((SymbolTable&)numflags)[name]; else return NULL; } /* int Flags :: GetDefineFlag (const char * name) const { return defflags.Used (name); } */ bool Flags :: GetDefineFlag (const string & name) const throw() { if (!defflags.Used (name)) return false; return defflags[name]; } xbool Flags :: GetDefineFlagX (const string & name) const throw() { if (!defflags.Used (name)) return maybe; return bool(defflags[name]); } const Array & Flags :: GetStringListFlag (const string & name) const { if (strlistflags.Used (name)) return *strlistflags[name]; else { static Array hstra(0); return hstra; } } const Array & Flags ::GetNumListFlag (const string & name) const { if (numlistflags.Used (name)) return *numlistflags[name]; else { static Array hnuma(0); return hnuma; } } const Flags & Flags ::GetFlagsFlag (const string & name) const { if (flaglistflags.Used (name)) return flaglistflags[name]; else { static Flags empty; return empty; } } const std::any& Flags:: GetAnyFlag(const std::string& name) const { if(anyflags.Used(name)) return anyflags[name]; static std::any empty; return empty; } bool Flags :: StringFlagDefined (const string & name) const { return strflags.Used (name); } bool Flags :: NumFlagDefined (const string &name) const { return numflags.Used (name); } bool Flags :: FlagsFlagDefined (const string &name) const { return flaglistflags.Used (name); } bool Flags :: StringListFlagDefined (const string & name) const { return strlistflags.Used (name); } bool Flags :: NumListFlagDefined (const string & name) const { return numlistflags.Used (name); } bool Flags :: AnyFlagDefined (const string& name) const { return anyflags.Used(name); } void Flags :: SaveFlags (ostream & str) const { for (int i = 0; i < strflags.Size(); i++) str << strflags.GetName(i) << " = " << strflags[i] << endl; for (int i = 0; i < numflags.Size(); i++) str << numflags.GetName(i) << " = " << numflags[i] << endl; for (int i = 0; i < defflags.Size(); i++) str << defflags.GetName(i) << " = " << (defflags[i] ? "_TRUE" : "_FALSE") << endl; for (int i = 0; i < flaglistflags.Size(); i++) str << flaglistflags.GetName(i) << " =*" << flaglistflags[i] << endl; for (int i = 0; i < numlistflags.Size(); i++) { str << numlistflags.GetName(i) << " = ["; int j = 0; for (j = 0; j + 1 < numlistflags[i]->Size(); ++j) str << (*numlistflags[i])[j] << ", "; if (numlistflags[i]->Size()) str << (*numlistflags[i])[j]; str << "]" << endl; } } void Flags :: SaveFlags (const char * filename) const { std::ofstream outfile (filename); SaveFlags(outfile); } void Flags :: PrintFlags (ostream & ost) const { for (int i = 0; i < strflags.Size(); i++) ost << strflags.GetName(i) << " = " << strflags[i] << endl; for (int i = 0; i < numflags.Size(); i++) ost << numflags.GetName(i) << " = " << numflags[i] << endl; for (int i = 0; i < defflags.Size(); i++) ost << defflags.GetName(i) << endl; for (int i = 0; i < strlistflags.Size(); i++) ost << strlistflags.GetName(i) << " = " << *strlistflags[i] << endl; for (int i = 0; i < numlistflags.Size(); i++) ost << numlistflags.GetName(i) << " = " << *numlistflags[i] << endl; for (int i = 0; i < flaglistflags.Size(); i++) ost << flaglistflags.GetName(i) << " = " << flaglistflags[i] << endl; } void Flags :: LoadFlags (const char * filename, SymbolTable * sf) { std::ifstream str(filename); LoadFlags(str,sf); } void Flags :: LoadFlags (std::istream & istr, SymbolTable * sf ) { char str[100]; char ch; // double val; while (istr.good()) { string name; string content; string line; getline(istr, line); std::istringstream line_stream(line); getline(line_stream, name, '='); name.erase(std::remove(name.begin(), name.end(), ' '), name.end()); getline(line_stream, content); content.erase(std::remove(content.begin(), content.end(), ' '), content.end()); // if (name[0] == '/' && name[1] == '/') // { // ch = 0; // while (ch != '\n' && istr.good()) // { // ch = istr.get(); // } // continue; // } if (strlen(content.c_str())==0) { SetFlag (name); continue; } else { std::istringstream content_stream(content); content_stream >> ch; if (ch != '*') { if (ch == '[') { // content_stream.putback (ch); // content_stream >> ch; string inner_string; getline(content_stream, inner_string, ']'); std::istringstream inner_string_stream(inner_string); Array values; Array strings; string cur; while (getline(inner_string_stream, cur, ',')) { char* endptr; double vald = strtod (cur.c_str(), &endptr); if (endptr != cur.c_str() && strings.Size() == 0) values.Append(vald); else strings.Append(cur); } if (strings.Size() > 0) SetFlag(name, strings); else SetFlag(name, values); } else { if(content == "_TRUE" || content == "_FALSE") { SetFlag(name, (content =="_TRUE") ? true : false); continue; } char* endptr; double vald = strtod (content.c_str(), &endptr); if (endptr != content.c_str()) SetFlag (name, vald); else SetFlag (name, content); } } else { content_stream.clear(); content_stream >> str; if (sf) SetFlag (name, (*sf)[str]); else throw Exception (" no symboltable of flags "); } } } } void Flags :: DoArchive(Archive & archive) { archive & strflags & numflags & defflags & numlistflags & strlistflags & flaglistflags; } void Flags :: Update(const Flags& other) { strflags.Update(other.strflags); numflags.Update(other.numflags); defflags.Update(other.defflags); numlistflags.Update(other.numlistflags); strlistflags.Update(other.strlistflags); flaglistflags.Update(other.flaglistflags); } void Flags :: SetCommandLineFlag (const char * st, SymbolTable * sf ) { //cout << "SetCommandLineFlag: flag = " << st << endl; std::istringstream inst( (char *)st); char name[100]; double val; if (st[0] != '-') { std::cerr << "flag must start with '-'" << endl; return; } // flag with double -- if (st[1] == '-') st++; const char * pos = strchr (st, '='); const char * posstar = strchr (st, '*'); const char * posbrack = strchr (st, '['); if (!pos) { // (cout) << "Add def flag: " << st+1 << endl; SetFlag (st+1); } else { //cout << "pos = " << pos << endl; strncpy (name, st+1, (pos-st)-1); name[pos-st-1] = 0; //cout << "name = " << name << endl; pos++; char * endptr = NULL; val = strtod (pos, &endptr); /* cout << "val = " << val << endl; cout << "isfinite = " << std::isfinite (val) << endl; cout << "isinf = " << std::isinf (val) << endl; cout << "pos = " << pos << ", endpos = " << endptr << endl; */ if (endptr != pos && !std::isfinite (val)) endptr = const_cast(pos); /* #ifdef WIN32 if(endptr != pos && !_finite(val)) endptr = const_cast(pos); #else #ifdef MACOS if(endptr != pos && (__isnand(val) || __isinfd(val))) endptr = const_cast(pos); #else #ifdef SUN #else if(endptr != pos && (std::isnan(val) || std::isinf(val))) endptr = const_cast(pos); #endif #endif #endif */ //cout << "val = " << val << endl; if (!posbrack) { if (posstar) { pos++; if (sf) SetFlag (name, (*sf)[pos]); else throw Exception (" no symboltable of flags "); } else if (endptr == pos) { // string-flag //(cout) << "Add String Flag: " << name << " = " << pos << endl; SetFlag (name, pos); } else { // num-flag //(cout) << "Add Num Flag: " << name << " = " << val << endl; SetFlag (name, val); } } else { // list-flag char hc; double val; val = strtod (posbrack+1, &endptr); if (endptr != posbrack+1) { Array values; std::istringstream ist(posbrack); ist >> hc; // '[' ist >> val; while (ist.good()) { values.Append (val); ist >> hc; // ',' ist >> val; } SetFlag (name, values); } else { // to be cleand up ... Array strs; posbrack++; char * hstr = new char[strlen(posbrack)+1]; strcpy (hstr, posbrack); char * chp = hstr; bool start = 1; while (*chp && *chp != ']') { if (start) strs.Append (chp); start = 0; if (*chp == ',') { *chp = 0; start = 1; } chp++; } *chp = 0; Array strings; for (int i = 0; i < strs.Size(); i++) strings.Append (string (strs[i])); SetFlag (name, strings); delete [] hstr; } } } } } // namespace ngcore