Sirikata
|
00001 /* Sirikata Configuration Options -- Sirikata Options 00002 * OptionValue.hpp 00003 * 00004 * Copyright (c) 2009, Daniel Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifndef _SIRIKATA_OPTIONVALUE_HPP_ 00034 #define _SIRIKATA_OPTIONVALUE_HPP_ 00035 00036 #include <sirikata/core/util/Any.hpp> 00037 00038 namespace Sirikata { 00039 class OptionSet; 00040 00041 // Strings 00042 00043 template <class T> class OptionValueType {public: 00044 static Any lexical_cast(const std::string &value){ 00045 T retval=T(); 00046 std::istringstream ss(value); 00047 ss>>retval; 00048 return retval; 00049 } 00050 }; 00051 template <> class OptionValueType<std::string> {public: 00052 static Any lexical_cast(const std::string &value){ 00053 return value; 00054 } 00055 }; 00056 00057 // Maps 00058 00059 template <class T> class OptionValueMap {public: 00061 static Any lexical_cast(const std::string &value){ 00062 T retval; 00063 std::string::size_type where=0,oldwhere=0; 00064 while((where=value.find(':',oldwhere))!=std::string::npos) { 00065 std::string key=value.substr(oldwhere,where-oldwhere); 00066 oldwhere=where+1; 00067 where=value.find('{',oldwhere); 00068 if (where!=std::string::npos) { 00069 int count=1; 00070 std::string::size_type value_begin=oldwhere=where+1; 00071 while ((where=value.find_first_of("{}",oldwhere))!=std::string::npos) { 00072 if (value[where]=='}') 00073 --count; 00074 else 00075 ++count; 00076 oldwhere=where+1; 00077 if (count==0){ 00078 std::string val=value.substr(value_begin,where-value_begin); 00079 retval[key]=val; 00080 break; 00081 } 00082 } 00083 } 00084 where=value.find(',',oldwhere); 00085 if (where==std::string::npos) break; 00086 oldwhere=where+1; 00087 } 00088 return retval; 00089 } 00090 }; 00091 00092 template <> class OptionValueType<std::map<std::string,std::string> > :public OptionValueMap<std::map<std::string,std::string> > {public: 00093 }; 00094 template <> class OptionValueType<std::tr1::unordered_map<std::string,std::string> > :public OptionValueMap<std::tr1::unordered_map<std::string,std::string> > {public: 00095 }; 00096 00097 // Lists 00098 00099 template <class T> 00100 class OptionValueList { 00101 public: 00103 static Any lexical_cast(const std::string &value){ 00104 T retval; 00105 00106 // Strip any [] around the list 00107 int32 list_start = 0, list_end = value.size(); 00108 while(list_start < (int32)value.size()) { 00109 if (value[list_start] == '[') { 00110 list_start++; 00111 break; 00112 } 00113 else if (value[list_start] == ' ' || value[list_start] == '\t') 00114 list_start++; 00115 else 00116 break; 00117 } 00118 while(list_end > 0) { 00119 if (value[list_end-1] == ']') { 00120 list_end--; 00121 break; 00122 } 00123 else if (value[list_end-1] == ' ' || value[list_end-1] == '\t') 00124 list_end--; 00125 else 00126 break; 00127 } 00128 00129 if (list_end - list_start <= 0) return retval; 00130 00131 int32 comma = list_start, last_comma = list_start-1; 00132 00133 while(true) { 00134 comma = (int32)value.find(',', last_comma+1); 00135 if (comma > list_end || comma == (int32)std::string::npos) 00136 comma = list_end; 00137 std::string elem = value.substr(last_comma+1, (comma-(last_comma+1))); 00138 if (elem.size() > 0) 00139 retval.push_back(elem); 00140 00141 // If we hit the end of the string, finish up 00142 if (comma >= list_end) 00143 break; 00144 00145 last_comma = comma; 00146 } 00147 return retval; 00148 } 00149 }; 00150 00151 template <> class OptionValueType<std::vector<std::string> > :public OptionValueList<std::vector<std::string> > {public: 00152 }; 00153 template <> class OptionValueType<std::list<std::string> > :public OptionValueList<std::list<std::string> > {public: 00154 }; 00155 00156 // Bool 00157 00158 template <> class OptionValueType<bool> {public: 00159 static Any lexical_cast(const std::string &value){ 00160 bool retval=false; 00161 if (value.size()){ 00162 if (value[0]=='T'||value[0]=='t'||value[0]=='1'||value[0]=='Y'||value[0]=='y') 00163 retval=true; 00164 } 00165 return retval; 00166 } 00167 }; 00168 class OptionRegistration; 00169 00173 class OptionValue{ 00174 Any mValue; 00175 std::string mDefaultValue; 00176 const char *mDefaultChar; 00177 const char* mDescription; 00178 std::tr1::function<Any(std::string)> mParser; 00179 std::tr1::function<void(const std::string&,Any,Any)>mChangeFunction; 00180 const char* mName; 00181 00182 static void noop(const std::string&,Any ,Any) { 00183 00184 } 00186 friend class OptionRegistration; 00188 friend class OptionSet; 00189 00190 public: 00191 00192 const Any*operator->()const { 00193 return &mValue; 00194 } 00195 Any*operator->() { 00196 return &mValue; 00197 } 00198 const Any*get()const { 00199 return &mValue; 00200 } 00201 Any* get() { 00202 return &mValue; 00203 } 00204 template <class T> T&as(){return mValue.as<T>();} 00205 template <class T> const T&as()const{return mValue.as<T>();} 00206 template <class T> T&unsafeAs(){return mValue.unsafeAs<T>();} 00207 template <class T> const T&unsafeAs()const{return mValue.unsafeAs<T>();} 00208 const char*description() const{ 00209 return mDescription; 00210 } 00211 const char *defaultValue() const{ 00212 return mDefaultChar?mDefaultChar:mDefaultValue.c_str(); 00213 } 00215 OptionValue& operator=(const OptionValue&other); 00216 00217 OptionValue() { 00218 mDefaultChar=NULL; 00219 mDescription="";mName=""; 00220 mChangeFunction=NULL; 00221 mParser=NULL; 00222 } 00231 template<class T>OptionValue(const char*option, const std::string&defaultValue, T type, const char*description, OptionValue**pointer=NULL):mDefaultChar(NULL){ 00232 mParser=std::tr1::function<Any(std::string)>(&T::lexical_cast); 00233 mName=option; 00234 mDefaultValue=defaultValue; 00235 mDescription=description; 00236 mChangeFunction=std::tr1::function<void(const std::string&, Any, Any)>(&OptionValue::noop); 00237 if (pointer) 00238 *pointer=this; 00239 } 00249 template<class T>OptionValue(const char* option, const std::string&defaultValue, T xtype, const char*description, std::tr1::function<void(const std::string&,Any,Any)>&changeFunction, OptionValue**pointer=NULL) :mDefaultChar(NULL){ 00250 mParser=std::tr1::function<Any(std::string)>(&T::lexical_cast); 00251 mName=option; 00252 mDescription=description; 00253 mDefaultValue=defaultValue; 00254 mChangeFunction=std::tr1::function<void(const std::string&, Any, Any)>(&OptionValue::noop); 00255 if (pointer) 00256 *pointer=this; 00257 } 00266 OptionValue(const char* option, const std::string&defaultValue, const char *description, const std::tr1::function<Any(std::string)>& parser, OptionValue**pointer=NULL) :mDefaultChar(NULL){ 00267 mParser=parser; 00268 mName=option; 00269 mDescription=description; 00270 mDefaultValue=defaultValue; 00271 mChangeFunction=&OptionValue::noop; 00272 if (pointer) 00273 *pointer=this; 00274 } 00284 OptionValue(const char* option, const std::string&defaultValue, const char* description, const std::tr1::function<Any(std::string)>& parser, const std::tr1::function<void(const std::string&, Any, Any)> &changeFunction, OptionValue**pointer=NULL) :mDefaultChar(NULL){ 00285 mParser=parser; 00286 mName=option; 00287 mDescription=description; 00288 mDefaultValue=defaultValue; 00289 mChangeFunction=changeFunction; 00290 if (pointer) 00291 *pointer=this; 00292 } 00293 00294 00295 00296 00297 00298 00299 00308 template<class T>OptionValue(const char*option, const char*defaultValue, T type, const char*description, OptionValue**pointer=NULL){ 00309 mParser=std::tr1::function<Any(std::string)>(&T::lexical_cast); 00310 mName=option; 00311 mDefaultChar=defaultValue; 00312 mDescription=description; 00313 mChangeFunction=std::tr1::function<void(const std::string&, Any, Any)>(&OptionValue::noop); 00314 if (pointer) 00315 *pointer=this; 00316 } 00326 template<class T>OptionValue(const char* option, const char*defaultValue, T xtype, const char*description, std::tr1::function<void(const std::string&,Any,Any)>&changeFunction, OptionValue**pointer=NULL) { 00327 mParser=std::tr1::function<Any(std::string)>(&T::lexical_cast); 00328 mName=option; 00329 mDescription=description; 00330 mDefaultChar=defaultValue; 00331 mChangeFunction=std::tr1::function<void(const std::string&, Any, Any)>(&OptionValue::noop); 00332 if (pointer) 00333 *pointer=this; 00334 } 00343 OptionValue(const char* option, const char*defaultValue, const char *description, const std::tr1::function<Any(std::string)>& parser, OptionValue**pointer=NULL) { 00344 mParser=parser; 00345 mName=option; 00346 mDescription=description; 00347 mDefaultChar=defaultValue; 00348 mChangeFunction=&OptionValue::noop; 00349 if (pointer) 00350 *pointer=this; 00351 } 00361 OptionValue(const char* option, const char*defaultValue, const char* description, const std::tr1::function<Any(std::string)>& parser, const std::tr1::function<void(const std::string&, Any, Any)> &changeFunction, OptionValue**pointer=NULL) { 00362 mParser=parser; 00363 mName=option; 00364 mDescription=description; 00365 mDefaultChar=defaultValue; 00366 mChangeFunction=changeFunction; 00367 if (pointer) 00368 *pointer=this; 00369 } 00370 00371 00372 00373 }; 00374 } 00375 #endif //_SIRIKATA_OPTIONVALUE_HPP_