55| | |__| __/ <\__ \ |_| \__ \ | || |\ || || __/ (_| | | \__ \ __/ | |
66| |_____\___|_|\_\___/\__, |___/ |___|_| \_|___|_| \__,_|_| |___/\___|_| |
77| |___/ |
8- | by Borovik Alexey |
98/===============================================================================================================/
109| All-in-one INI file parser |
1110| Provides convenient cross-platform class to load and save .INI files |
5049#include < algorithm> // for std::transform
5150#include < functional> // for std::not1, std::ptr_fun
5251#include < cctype> // for std::isspace()
53- #include < locale > // for std::isspace () in current locale
52+ #include < ctype.h > // for tolower () and toupper()
5453#include < fstream> // for std::fstream
5554#include < string.h> // for strlen()
55+ #include < iomanip> // for std::setprecision
5656/* ---------------------------------------------------------------------------------------------------------------/
5757/ Defines & Settings
5858/---------------------------------------------------------------------------------------------------------------*/
@@ -113,47 +113,45 @@ namespace INI
113113 std::transform (str.begin (), str.end (), str.begin (), ::toupper);
114114 }
115115
116+ // / stream to be used for conversions
117+ class convstream : public std ::stringstream
118+ {
119+ public:
120+ convstream () {*this << std::setprecision (17 ) << std::boolalpha;}
121+ };
122+
116123 // / Convert anything (int, double etc) to string
117124 template <class T > std::string t_to_string (const T& i)
118125 {
119- std::stringstream ss;
126+ convstream ss;
120127 std::string s;
121128 ss << i;
122129 s = ss.str ();
123130 return s;
124131 }
125132 // / Special case for string (to avoid overheat)
126- template <> std::string t_to_string<std::string>(const std::string& i)
133+ template <> inline std::string t_to_string<std::string>(const std::string& i)
127134 {
128135 return i;
129136 }
130- // / Special case for boolean value
131- template <> std::string t_to_string<bool >(const bool & i)
132- {
133- std::stringstream ss;
134- std::string s;
135- ss << std::boolalpha << i;
136- s = ss.str ();
137- return s;
138- }
139137
140138 // / Convert string to anything (int, double, etc)
141139 template <class T > T string_to_t (const std::string& v)
142140 {
143- std::stringstream ss;
141+ convstream ss;
144142 T out;
145143 ss << v;
146144 ss >> out;
147145 return out;
148146 }
149147 // / Special case for string
150- template <> std::string string_to_t <std::string>(const std::string& v)
148+ template <> inline std::string string_to_t <std::string>(const std::string& v)
151149 {
152150 return v;
153151 }
154152 // / Special case for boolean value
155153 // / std::boolalpha only covers 'true' or 'false', while we have more cases
156- template <> bool string_to_t <bool >(const std::string& v)
154+ template <> inline bool string_to_t <bool >(const std::string& v)
157155 {
158156 if (!v.size ())
159157 return false ;
@@ -162,15 +160,23 @@ namespace INI
162160 return false ;
163161 }
164162
163+ // Calling isspace with signed chars in Visual Studio causes assert failure in DEBUG builds
164+ // This hack is approved by MS itself
165+ #if defined (_MSC_VER)
166+ static inline int __in_isspace (int ch) {return std::isspace ((unsigned char )ch);}
167+ #else
168+ # define __in_isspace std::isspace
169+ #endif
170+
165171 // Trim string from start
166172 static inline std::string <rim (std::string &s) {
167- s.erase (s.begin (), std::find_if (s.begin (), s.end (), std::not1 (std::ptr_fun<int , int >(std::isspace ))));
173+ s.erase (s.begin (), std::find_if (s.begin (), s.end (), std::not1 (std::ptr_fun<int , int >(__in_isspace ))));
168174 return s;
169175 }
170176
171177 // Trim string from end
172178 static inline std::string &rtrim (std::string &s) {
173- s.erase (std::find_if (s.rbegin (), s.rend (), std::not1 (std::ptr_fun<int , int >(std::isspace ))).base (), s.end ());
179+ s.erase (std::find_if (s.rbegin (), s.rend (), std::not1 (std::ptr_fun<int , int >(__in_isspace ))).base (), s.end ());
174180 return s;
175181 }
176182
@@ -225,7 +231,7 @@ namespace INI
225231 }
226232
227233 // Replace every occurrence of @param what to @param ret in @param str
228- std::string& str_replace (std::string& str, const std::string& what, const std::string& rep)
234+ static inline std::string& str_replace (std::string& str, const std::string& what, const std::string& rep)
229235 {
230236 int diff = rep.size () - what.size () + 1 ;
231237 for (size_t pos = 0 ; ;pos += diff)
@@ -239,7 +245,7 @@ namespace INI
239245 }
240246
241247 // normalize path (for relative path to be system-independent)
242- void normalize_path (std::string& path)
248+ static inline void normalize_path (std::string& path)
243249 {
244250#ifdef WIN32
245251 str_replace (path," /" ," \\ " );
@@ -249,7 +255,7 @@ namespace INI
249255 }
250256
251257 // get file path (excluding file name)
252- std::string file_path (const std::string& file_fullname)
258+ static inline std::string file_path (const std::string& file_fullname)
253259 {
254260 size_t pos = file_fullname.rfind (SYSTEM_PATH_DELIM);
255261 if (pos == std::string::npos)
@@ -258,7 +264,7 @@ namespace INI
258264 }
259265
260266 // get file name (excluding file path)
261- std::string file_name (const std::string& file_fullname)
267+ static inline std::string file_name (const std::string& file_fullname)
262268 {
263269 size_t pos = file_fullname.rfind (SYSTEM_PATH_DELIM);
264270 if (pos == std::string::npos)
@@ -267,7 +273,7 @@ namespace INI
267273 }
268274
269275 // check whether path is absolute
270- bool path_is_absolute (const std::string& path)
276+ static inline bool path_is_absolute (const std::string& path)
271277 {
272278#ifdef WIN32
273279 if (path.size () < 2 )
@@ -288,7 +294,7 @@ namespace INI
288294 }
289295
290296 // check whether path is relative
291- bool path_is_relative (const std::string& path) {return !path_is_absolute (path);}
297+ static inline bool path_is_relative (const std::string& path) {return !path_is_absolute (path);}
292298
293299 /* ---------------------------------------------------------------------------------------------------------------/
294300 / INI-related classes
@@ -332,7 +338,7 @@ namespace INI
332338 return T ();
333339 return string_to_t <T>(_ptr->str );
334340 }
335- inline void Set (const std::string& str)
341+ void Set (const std::string& str)
336342 {
337343 Decrement ();
338344 _ptr = new val_cont ();
@@ -388,7 +394,7 @@ namespace INI
388394 std::string str;
389395 size_t count;
390396 };
391- inline void Decrement ()
397+ void Decrement ()
392398 {
393399 if (!_ptr)
394400 return ;
@@ -399,7 +405,7 @@ namespace INI
399405 _ptr = NULL ;
400406 }
401407 }
402- inline void Increment ()
408+ void Increment ()
403409 {
404410 if (_ptr)
405411 _ptr->count ++;
@@ -524,7 +530,7 @@ namespace INI
524530 std::vector<Value> vector;
525531 size_t count;
526532 };
527- inline void Decrement ()
533+ void Decrement ()
528534 {
529535 if (!_ptr)
530536 return ;
@@ -535,7 +541,7 @@ namespace INI
535541 _ptr = NULL ;
536542 }
537543 }
538- inline void Increment ()
544+ void Increment ()
539545 {
540546 if (_ptr)
541547 _ptr->count ++;
@@ -554,17 +560,17 @@ namespace INI
554560 ar_cont* _ptr;
555561 };
556562
557- template <> void Value::Set<Array> (const Array& value)
563+ template <> inline void Value::Set<Array> (const Array& value)
558564 {
559565 Set (value.ToString ());
560566 }
561- template <> Array Value::Get<Array>() const
567+ template <> inline Array Value::Get<Array>() const
562568 {
563569 if (!_ptr)
564570 return Array ();
565571 return Array (_ptr->str );
566572 }
567- Array Value::AsArray () const {return Get<Array>();}
573+ inline Array Value::AsArray () const {return Get<Array>();}
568574
569575 /* ---------------------------------------------------------------------------------------------------------------/
570576 / INI file creation and parsing
@@ -1093,6 +1099,7 @@ namespace INI
10931099 else
10941100 fpath = incname;
10951101 std::ifstream file (fpath.c_str (), std::ios::in);
1102+ std::string prevfn = _result.file_name ;
10961103 _result.file_name = fpath;
10971104 if (!file.is_open ())
10981105 {
@@ -1106,6 +1113,7 @@ namespace INI
11061113 scname = def_section;
11071114 if (!ParseStream (file,scname,file_path (fpath),pmap))
11081115 return 0 ;
1116+ _result.file_name = prevfn;
11091117 continue ;
11101118 }
11111119 // Add comment (it can be set with any string type, other than EMPTY and ERROR)
@@ -1185,32 +1193,32 @@ namespace INI
11851193 /* -----------------------------------------------------------------------------------------------------------/
11861194 / Some functions left unimplemented
11871195 /-----------------------------------------------------------------------------------------------------------*/
1188- Section* Section::GetParent () {return _file->GetParentSection (this );}
1189- Section* Section::FindParent () const {return _file->FindParentSection (this );}
1190- Section* Section::GetSubSection (const std::string& name) {return _file->GetSubSection (this ,name);}
1191- Section* Section::FindSubSection (const std::string& name) const {return _file->FindSubSection (this ,name);}
1192- SectionVector Section::FindSubSections () const {return _file->FindSubSections (this );}
1193- void Section::Save (std::ostream& stream) const {return _file->Save (stream,this );}
1196+ inline Section* Section::GetParent () {return _file->GetParentSection (this );}
1197+ inline Section* Section::FindParent () const {return _file->FindParentSection (this );}
1198+ inline Section* Section::GetSubSection (const std::string& name) {return _file->GetSubSection (this ,name);}
1199+ inline Section* Section::FindSubSection (const std::string& name) const {return _file->FindSubSection (this ,name);}
1200+ inline SectionVector Section::FindSubSections () const {return _file->FindSubSections (this );}
1201+ inline void Section::Save (std::ostream& stream) const {return _file->Save (stream,this );}
11941202}
11951203/* ---------------------------------------------------------------------------------------------------------------/
11961204/ Stream operators
11971205/---------------------------------------------------------------------------------------------------------------*/
1198- std::ostream& operator << (std::ostream& stream, const INI::File& file)
1206+ static inline std::ostream& operator << (std::ostream& stream, const INI::File& file)
11991207{
12001208 file.Save (stream);
12011209 return stream;
12021210}
1203- std::ostream& operator << (std::ostream& stream, const INI::Section* sect)
1211+ static inline std::ostream& operator << (std::ostream& stream, const INI::Section* sect)
12041212{
12051213 sect->Save (stream);
12061214 return stream;
12071215}
1208- std::ostream& operator << (std::ostream& stream, const INI::Array& ar)
1216+ static inline std::ostream& operator << (std::ostream& stream, const INI::Array& ar)
12091217{
12101218 stream << ar.ToValue ().AsString ();
12111219 return stream;
12121220}
1213- std::istream& operator >> (std::istream& stream, INI::File& file)
1221+ static inline std::istream& operator >> (std::istream& stream, INI::File& file)
12141222{
12151223 file.Load (stream,false );
12161224 return stream;
@@ -1231,4 +1239,4 @@ std::istream& operator>> (std::istream& stream, INI::File& file)
12311239#undef SYSTEM_PATH_DELIM
12321240// Note: error definitions are left
12331241
1234- #endif
1242+ #endif
0 commit comments