Skip to content

Commit 8d8e556

Browse files
committed
[-] Some of the functions were not 'inline', which caused linker error in some cases
[-] Microsoft bug, due witch debug build of the program could crash when reading files with non-english characters (https://connect.microsoft.com/VisualStudio/feedback/details/932876/calling-isdigit-with-a-signed-char-1-results-in-a-assert-failure-in-debug-compiles) [+] Double precision is now set
1 parent ee6169e commit 8d8e556

4 files changed

Lines changed: 55 additions & 47 deletions

File tree

AUTHORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Author: Borovik Alexey <alexey@borovik.me>
1+
Author: Lek.sys <alexey@borovik.me>

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Lek'sys INI Parser
1+
# Leksys' INI Parser
22

33
Crossplatform all-in-one INI-file parser, written on C++ with STL
44
```
@@ -9,7 +9,7 @@ Crossplatform all-in-one INI-file parser, written on C++ with STL
99
| | |__| __/ <\__ \ |_| \__ \ | || |\ || || __/ (_| | | \__ \ __/ | |
1010
| |_____\___|_|\_\___/\__, |___/ |___|_| \_|___|_| \__,_|_| |___/\___|_| |
1111
| |___/ |
12-
| by Borovik Alexey |
12+
| |
1313
+====================================================================================+
1414
```
1515

iniparser.hpp

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
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 |
@@ -50,9 +49,10 @@
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 &ltrim(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

test_app.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,4 @@ int main(int argc, char** argv)
242242
// [SUCCESS]
243243
std::cout << "!!! [SUCCESS] !!! " << std::endl;
244244
return 0;
245-
}
245+
}

0 commit comments

Comments
 (0)