vars.cpp
Go to the documentation of this file.
00001 /* This file is part of the Pangolin Project.
00002  * http://github.com/stevenlovegrove/Pangolin
00003  *
00004  * Copyright (c) 2011 Steven Lovegrove
00005  *
00006  * Permission is hereby granted, free of charge, to any person
00007  * obtaining a copy of this software and associated documentation
00008  * files (the "Software"), to deal in the Software without
00009  * restriction, including without limitation the rights to use,
00010  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following
00013  * conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be
00016  * included in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00020  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00021  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00022  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00023  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  * OTHER DEALINGS IN THE SOFTWARE.
00026  */
00027 
00028 #include "vars.h"
00029 
00030 #include <iostream>
00031 #include <fstream>
00032 #include <sstream>
00033 #include <boost/algorithm/string.hpp>
00034 #include <boost/algorithm/string/replace.hpp>
00035 
00036 using namespace std;
00037 using namespace boost;
00038 
00039 namespace pangolin
00040 {
00041 
00042 boost::ptr_unordered_map<string,_Var> vars;
00043 vector<NewVarCallback> new_var_callbacks;
00044 vector<GuiVarChangedCallback> gui_var_changed_callbacks;
00045 
00046 void RegisterNewVarCallback(NewVarCallbackFn callback, void* data, const std::string& filter)
00047 {
00048     new_var_callbacks.push_back(NewVarCallback(filter,callback,data));
00049 }
00050 
00051 void RegisterGuiVarChangedCallback(GuiVarChangedCallbackFn callback, void* data, const std::string& filter)
00052 {
00053     gui_var_changed_callbacks.push_back(GuiVarChangedCallback(filter,callback,data));
00054 }
00055 
00056 // Find the open brace preceeded by '$'
00057 const char* FirstOpenBrace(const char* str)
00058 {
00059     bool symbol = false;
00060 
00061     for(; *str != '\0'; ++str )
00062     {
00063         if( *str == '$')
00064         {
00065             symbol = true;
00066         }
00067         else
00068         {
00069             if( symbol )
00070             {
00071                 if( *str == '{' )
00072                 {
00073                     return str;
00074                 }
00075                 else
00076                 {
00077                     symbol = false;
00078                 }
00079             }
00080         }
00081     }
00082     return 0;
00083 }
00084 
00085 // Find the first matching end brace. str includes open brace
00086 const char* MatchingEndBrace(const char* str)
00087 {
00088     int b = 0;
00089     for(; *str != '\0'; ++str )
00090     {
00091         if( *str == '{' )
00092         {
00093             ++b;
00094         }
00095         else if( *str == '}' )
00096         {
00097             --b;
00098             if( b == 0 )
00099             {
00100                 return str;
00101             }
00102         }
00103     }
00104     return 0;
00105 }
00106 
00107 // Recursively expand val
00108 string ProcessVal(const string& val )
00109 {
00110     string expanded = val;
00111 
00112     while(true)
00113     {
00114         const char* brace = FirstOpenBrace(expanded.c_str());
00115         if(brace)
00116         {
00117             const char* endbrace = MatchingEndBrace(brace);
00118             if( endbrace )
00119             {
00120                 iterator_range<const char*> out(brace-1,endbrace+1);
00121                 iterator_range<const char*> in(brace+1,endbrace);
00122                 string inexpand = ProcessVal(copy_range<string>(in));
00123                 Var<string> var(inexpand,"#");
00124                 if( !((const string)var).compare("#"))
00125                 {
00126                     std::cerr << "Unabled to expand: [" << inexpand << "].\nMake sure it is defined and terminated with a semi-colon." << endl << endl;
00127                 }
00128                 ostringstream oss;
00129                 oss << copy_range<string>(iterator_range<const char*>(expanded.c_str(), brace-1));
00130                 oss << (const string)var;
00131                 oss << copy_range<string>(iterator_range<const char*>(endbrace+1, expanded.c_str() + expanded.length() ));
00132                 expanded = oss.str();
00133 //        expanded = replace_range_copy(expanded,out,(const string)var);
00134 //        cout << copy_range<std::string>(in) << endl;
00135                 continue;
00136             }
00137         }
00138         break;
00139     }
00140 
00141     return expanded;
00142 }
00143 
00144 void AddVar(const string& name, const string& val )
00145 {
00146     boost::ptr_unordered_map<std::string,_Var>::iterator vi = vars.find(name);
00147     const bool exists_already = vi != vars.end();
00148 
00149     string full = ProcessVal(val);
00150     Var<string> var(name);
00151     var = full;
00152 
00153     // Mark as upgradable if unique
00154     if(!exists_already)
00155     {
00156         var.var->generic = true;
00157     }
00158 }
00159 
00160 #ifdef ALIAS
00161 void AddAlias(const string& alias, const string& name)
00162 {
00163     boost::ptr_unordered_map<std::string,_Var>::iterator vi = vars.find(name);
00164 
00165     if( vi != vars.end() )
00166     {
00167         //cout << "Adding Alias " << alias << " to " << name << endl;
00168         _Var * v = vi->second;
00169         vars[alias].create(v->val,v->val_default,v->type_name);
00170         vars[alias].meta_friendly = alias;
00171         v->generic = false;
00172         vars[alias].generic = false;
00173     }
00174     else
00175     {
00176         cout << "Variable " << name << " does not exist to alias." << endl;
00177     }
00178 }
00179 #endif
00180 
00181 void ParseVarsFile(const string& filename)
00182 {
00183     ifstream f(filename.c_str());
00184 
00185     if( f.is_open() )
00186     {
00187         while( !f.bad() && !f.eof())
00188         {
00189             const int c = f.peek();
00190 
00191             if( isspace(c) )
00192             {
00193                 // ignore leading whitespace
00194                 f.get();
00195             }
00196             else
00197             {
00198                 if( c == '#' || c == '%' )
00199                 {
00200                     // ignore lines starting # or %
00201                     string comment;
00202                     getline(f,comment);
00203                 }
00204                 else
00205                 {
00206                     // Otherwise, find name and value, seperated by '=' and ';'
00207                     string name;
00208                     string val;
00209                     getline(f,name,'=');
00210                     getline(f,val,';');
00211                     boost::trim_if(name, boost::is_any_of(" \t\n\r"));
00212                     boost::trim_if(val, boost::is_any_of(" \t\n\r"));
00213 
00214                     if( name.size() >0 && val.size() > 0 )
00215                     {
00216                         if( !val.substr(0,1).compare("@") )
00217                         {
00218 #ifdef ALIAS
00219                             AddAlias(name,val.substr(1));
00220 #endif
00221                         }
00222                         else
00223                         {
00224                             AddVar(name,val);
00225                         }
00226                     }
00227                 }
00228             }
00229         }
00230         f.close();
00231     }
00232     else
00233     {
00234         cerr << "Unable to open '" << filename << "' for configuration data" << endl;
00235     }
00236 }
00237 
00238 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


pangolin_wrapper
Author(s): Todor Stoyanov
autogenerated on Wed Feb 13 2013 14:03:25