Coverage Report

Created: 2026-08-13 06:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreStringConverter.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#include "OgreStableHeaders.h"
29
30
// A quick define to overcome different names for the same function
31
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT
32
#   define strtod_l _strtod_l
33
#   define strtoul_l _strtoul_l
34
#   define strtol_l _strtol_l
35
#   define strtoull_l _strtoull_l
36
#   define strtoll_l _strtoll_l
37
#endif
38
39
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN || \
40
  (OGRE_PLATFORM == OGRE_PLATFORM_LINUX && OGRE_NO_LOCALE_STRCONVERT == 1)
41
#   define strtod_l(ptr, end, l) strtod(ptr, end)
42
#   define strtoul_l(ptr, end, base, l) strtoul(ptr, end, base)
43
#   define strtol_l(ptr, end, base, l) strtol(ptr, end, base)
44
#   define strtoull_l(ptr, end, base, l) strtoull(ptr, end, base)
45
#   define strtoll_l(ptr, end, base, l) strtoll(ptr, end, base)
46
#endif
47
48
#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT) && !defined(__MINGW32__)
49
#   define LC_NUMERIC_MASK LC_NUMERIC
50
#   define newlocale(cat, loc, base) _create_locale(cat, loc)
51
#endif
52
53
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN || defined(__MINGW32__)
54
#   define newlocale(cat, loc, base) 0
55
#endif
56
57
#ifdef __MINGW32__
58
#define _strtoull_l _strtoul_l
59
#define _strtoll_l _strtol_l
60
#endif
61
62
namespace Ogre {
63
    locale_t StringConverter::_numLocale = newlocale(LC_NUMERIC_MASK, OGRE_DEFAULT_LOCALE, NULL);
64
65
    template<typename T>
66
    String StringConverter::_toString(T val, uint16 width, char fill, std::ios::fmtflags flags)
67
0
    {
68
0
        StringStream stream;
69
0
        stream.width(width);
70
0
        stream.fill(fill);
71
0
        if (flags & std::ios::basefield) {
72
0
            stream.setf(flags, std::ios::basefield);
73
0
            stream.setf((flags & ~std::ios::basefield) | std::ios::showbase);
74
0
        }
75
0
        else if (flags)
76
0
            stream.setf(flags);
77
78
0
        stream << val;
79
80
0
        return stream.str();
81
0
    }
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Ogre::StringConverter::_toString<int>(int, unsigned short, char, unsigned int)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Ogre::StringConverter::_toString<unsigned int>(unsigned int, unsigned short, char, unsigned int)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Ogre::StringConverter::_toString<unsigned long>(unsigned long, unsigned short, char, unsigned int)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Ogre::StringConverter::_toString<unsigned long long>(unsigned long long, unsigned short, char, unsigned int)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Ogre::StringConverter::_toString<long>(long, unsigned short, char, unsigned int)
82
83
    //-----------------------------------------------------------------------
84
    String StringConverter::toString(float val, unsigned short precision,
85
                                     unsigned short width, char fill, std::ios::fmtflags flags)
86
0
    {
87
0
        StringStream stream;
88
0
        stream.precision(precision);
89
0
        stream.width(width);
90
0
        stream.fill(fill);
91
0
        if (flags)
92
0
            stream.setf(flags);
93
0
        stream << val;
94
0
        return stream.str();
95
0
    }
96
97
    //-----------------------------------------------------------------------
98
    String StringConverter::toString(double val, unsigned short precision,
99
                                     unsigned short width, char fill, std::ios::fmtflags flags)
100
0
    {
101
0
        StringStream stream;
102
0
        stream.precision(precision);
103
0
        stream.width(width);
104
0
        stream.fill(fill);
105
0
        if (flags)
106
0
            stream.setf(flags);
107
0
        stream << val;
108
0
        return stream.str();
109
0
    }
110
111
    //-----------------------------------------------------------------------
112
    String StringConverter::toString(int32 val,
113
        unsigned short width, char fill, std::ios::fmtflags flags)
114
0
    {
115
0
        return _toString(val, width, fill, flags);
116
0
    }
117
    //-----------------------------------------------------------------------
118
    String StringConverter::toString(uint32 val,
119
        unsigned short width, char fill, std::ios::fmtflags flags)
120
0
    {
121
0
        return _toString(val, width, fill, flags);
122
0
    }
123
    //-----------------------------------------------------------------------
124
    String StringConverter::toString(unsigned long val,
125
        unsigned short width, char fill, std::ios::fmtflags flags)
126
0
    {
127
0
        return _toString(val, width, fill, flags);
128
0
    }
129
    //-----------------------------------------------------------------------
130
    String StringConverter::toString(unsigned long long val,
131
        unsigned short width, char fill, std::ios::fmtflags flags)
132
0
    {
133
0
        return _toString(val, width, fill, flags);
134
0
    }
135
    //-----------------------------------------------------------------------
136
    String StringConverter::toString(long val,
137
        unsigned short width, char fill, std::ios::fmtflags flags)
138
0
    {
139
0
        return _toString(val, width, fill, flags);
140
0
    }
141
    //-----------------------------------------------------------------------
142
    String StringConverter::toString(const Vector2& val)
143
0
    {
144
0
        StringStream stream;
145
0
        stream << val.x << " " << val.y;
146
0
        return stream.str();
147
0
    }
148
    //-----------------------------------------------------------------------
149
    String StringConverter::toString(const Vector3& val)
150
0
    {
151
0
        StringStream stream;
152
0
        stream << val.x << " " << val.y << " " << val.z;
153
0
        return stream.str();
154
0
    }
155
    //-----------------------------------------------------------------------
156
    String StringConverter::toString(const Vector4& val)
157
0
    {
158
0
        StringStream stream;
159
0
        stream << val.x << " " << val.y << " " << val.z << " " << val.w;
160
0
        return stream.str();
161
0
    }
162
    //-----------------------------------------------------------------------
163
    String StringConverter::toString(const Matrix3& val)
164
0
    {
165
0
        StringStream stream;
166
0
        stream << val[0][0] << " "
167
0
            << val[0][1] << " "             
168
0
            << val[0][2] << " "             
169
0
            << val[1][0] << " "             
170
0
            << val[1][1] << " "             
171
0
            << val[1][2] << " "             
172
0
            << val[2][0] << " "             
173
0
            << val[2][1] << " "             
174
0
            << val[2][2];
175
0
        return stream.str();
176
0
    }
177
    //-----------------------------------------------------------------------
178
    String StringConverter::toString(bool val, bool yesNo)
179
0
    {
180
0
        if (val)
181
0
        {
182
0
            if (yesNo)
183
0
            {
184
0
                return "yes";
185
0
            }
186
0
            else
187
0
            {
188
0
                return "true";
189
0
            }
190
0
        }
191
0
        else
192
0
            if (yesNo)
193
0
            {
194
0
                return "no";
195
0
            }
196
0
            else
197
0
            {
198
0
                return "false";
199
0
            }
200
0
    }
201
    //-----------------------------------------------------------------------
202
    String StringConverter::toString(const Matrix4& val)
203
0
    {
204
0
        StringStream stream;
205
0
        stream << val[0][0] << " "
206
0
            << val[0][1] << " "             
207
0
            << val[0][2] << " "             
208
0
            << val[0][3] << " "             
209
0
            << val[1][0] << " "             
210
0
            << val[1][1] << " "             
211
0
            << val[1][2] << " "             
212
0
            << val[1][3] << " "             
213
0
            << val[2][0] << " "             
214
0
            << val[2][1] << " "             
215
0
            << val[2][2] << " "             
216
0
            << val[2][3] << " "             
217
0
            << val[3][0] << " "             
218
0
            << val[3][1] << " "             
219
0
            << val[3][2] << " "             
220
0
            << val[3][3];
221
0
        return stream.str();
222
0
    }
223
    //-----------------------------------------------------------------------
224
    String StringConverter::toString(const Quaternion& val)
225
0
    {
226
0
        StringStream stream;
227
0
        stream  << val.w << " " << val.x << " " << val.y << " " << val.z;
228
0
        return stream.str();
229
0
    }
230
    //-----------------------------------------------------------------------
231
    String StringConverter::toString(const ColourValue& val)
232
0
    {
233
0
        StringStream stream;
234
0
        stream << val.r << " " << val.g << " " << val.b << " " << val.a;
235
0
        return stream.str();
236
0
    }
237
    //-----------------------------------------------------------------------
238
    String StringConverter::toString(const StringVector& val)
239
7.26k
    {
240
7.26k
        StringStream stream;
241
7.26k
        StringVector::const_iterator i, iend, ibegin;
242
7.26k
        ibegin = val.begin();
243
7.26k
        iend = val.end();
244
17.9k
        for (i = ibegin; i != iend; ++i)
245
10.6k
        {
246
10.6k
            if (i != ibegin)
247
3.41k
                stream << " ";
248
249
10.6k
            stream << *i; 
250
10.6k
        }
251
7.26k
        return stream.str();
252
7.26k
    }
253
254
    //-----------------------------------------------------------------------
255
    template <typename T> static bool assignValid(bool valid, const T& val, T& ret)
256
36.9k
    {
257
36.9k
        if (valid)
258
32.0k
            ret = val;
259
36.9k
        return valid;
260
36.9k
    }
OgreStringConverter.cpp:bool Ogre::assignValid<float>(bool, float const&, float&)
Line
Count
Source
256
26.3k
    {
257
26.3k
        if (valid)
258
25.6k
            ret = val;
259
26.3k
        return valid;
260
26.3k
    }
Unexecuted instantiation: OgreStringConverter.cpp:bool Ogre::assignValid<double>(bool, double const&, double&)
OgreStringConverter.cpp:bool Ogre::assignValid<int>(bool, int const&, int&)
Line
Count
Source
256
876
    {
257
876
        if (valid)
258
576
            ret = val;
259
876
        return valid;
260
876
    }
Unexecuted instantiation: OgreStringConverter.cpp:bool Ogre::assignValid<long>(bool, long const&, long&)
Unexecuted instantiation: OgreStringConverter.cpp:bool Ogre::assignValid<unsigned long>(bool, unsigned long const&, unsigned long&)
Unexecuted instantiation: OgreStringConverter.cpp:bool Ogre::assignValid<unsigned long long>(bool, unsigned long long const&, unsigned long long&)
OgreStringConverter.cpp:bool Ogre::assignValid<unsigned int>(bool, unsigned int const&, unsigned int&)
Line
Count
Source
256
9.77k
    {
257
9.77k
        if (valid)
258
5.84k
            ret = val;
259
9.77k
        return valid;
260
9.77k
    }
261
262
    bool StringConverter::parse(const String& val, float& ret)
263
26.3k
    {
264
26.3k
        char* end;
265
26.3k
        auto tmp = (float)strtod_l(val.c_str(), &end, _numLocale);
266
26.3k
        return assignValid(val.c_str() != end, tmp, ret);
267
26.3k
    }
268
    bool StringConverter::parse(const String& val, double& ret)
269
0
    {
270
0
        char* end;
271
0
        auto tmp = strtod_l(val.c_str(), &end, _numLocale);
272
0
        return assignValid(val.c_str() != end, tmp, ret);
273
0
    }
274
    //-----------------------------------------------------------------------
275
    bool StringConverter::parse(const String& val, int32& ret)
276
876
    {
277
876
        char* end;
278
876
        auto tmp = (int32)strtol_l(val.c_str(), &end, 0, _numLocale);
279
876
        return assignValid(val.c_str() != end, tmp, ret);
280
876
    }
281
    //-----------------------------------------------------------------------
282
    bool StringConverter::parse(const String& val, int64& ret)
283
0
    {
284
0
        char* end;
285
0
        int64 tmp = strtoll_l(val.c_str(), &end, 0, _numLocale);
286
0
        return assignValid(val.c_str() != end, tmp, ret);
287
0
    }
288
    //-----------------------------------------------------------------------
289
    bool StringConverter::parse(const String& val, unsigned long& ret)
290
0
    {
291
0
        char* end;
292
0
        unsigned long tmp = strtoull_l(val.c_str(), &end, 0, _numLocale);
293
0
        return assignValid(val.c_str() != end, tmp, ret);
294
0
    }
295
    bool StringConverter::parse(const String& val, unsigned long long& ret)
296
0
    {
297
0
        char* end;
298
0
        unsigned long long tmp = strtoull_l(val.c_str(), &end, 0, _numLocale);
299
0
        return assignValid(val.c_str() != end, tmp, ret);
300
0
    }
301
    //-----------------------------------------------------------------------
302
    bool StringConverter::parse(const String& val, uint32& ret)
303
9.77k
    {
304
9.77k
        char* end;
305
9.77k
        auto tmp = (uint32)strtoul_l(val.c_str(), &end, 0, _numLocale);
306
9.77k
        return assignValid(val.c_str() != end, tmp, ret);
307
9.77k
    }
308
    bool StringConverter::parse(const String& val, bool& ret)
309
0
    {
310
        //FIXME Returns both parsed value and error in same value - ambiguous.
311
        // Suggested alternatives: implement exception handling or make either
312
        // error or parsed value a parameter.
313
0
        if ((StringUtil::startsWith(val, "true") || StringUtil::startsWith(val, "yes")
314
0
             || StringUtil::startsWith(val, "1") ||  StringUtil::startsWith(val, "on")))
315
0
            ret = true;
316
0
        else if ((StringUtil::startsWith(val, "false") || StringUtil::startsWith(val, "no")
317
0
                  || StringUtil::startsWith(val, "0") ||  StringUtil::startsWith(val, "off")))
318
0
            ret = false;
319
0
        else
320
0
            return false;
321
322
0
        return true;
323
0
    }
324
325
    static bool parseReals(const String& val, Real* dst, size_t n)
326
0
    {
327
        // Split on space
328
0
        std::vector<String> vec = StringUtil::split(val);
329
0
        if(vec.size() != n)
330
0
            return false;
331
332
0
        bool ret = true;
333
0
        for(size_t i = 0; i < n; i++)
334
0
            ret &= StringConverter::parse(vec[i], dst[i]);
335
0
        return ret;
336
0
    }
337
338
    //-----------------------------------------------------------------------
339
    bool StringConverter::parse(const String& val, Vector2& ret)
340
0
    {
341
0
        return parseReals(val, ret.ptr(), 2);
342
0
    }
343
    //-----------------------------------------------------------------------
344
    bool StringConverter::parse(const String& val, Vector3& ret)
345
0
    {
346
0
        return parseReals(val, ret.ptr(), 3);
347
0
    }
348
    //-----------------------------------------------------------------------
349
    bool StringConverter::parse(const String& val, Vector4& ret)
350
0
    {
351
0
        return parseReals(val, ret.ptr(), 4);
352
0
    }
353
    //-----------------------------------------------------------------------
354
    bool StringConverter::parse(const String& val, Matrix3& ret)
355
0
    {
356
0
        return parseReals(val, &ret[0][0], 9);
357
0
    }
358
    //-----------------------------------------------------------------------
359
    bool StringConverter::parse(const String& val, Matrix4& ret)
360
0
    {
361
0
        return parseReals(val, &ret[0][0], 16);
362
0
    }
363
    //-----------------------------------------------------------------------
364
    bool StringConverter::parse(const String& val, Quaternion& ret)
365
0
    {
366
0
        return parseReals(val, ret.ptr(), 4);
367
0
    }
368
    //-----------------------------------------------------------------------
369
    bool StringConverter::parse(const String& val, ColourValue& ret)
370
0
    {
371
        // Split on space
372
0
        std::vector<String> vec = StringUtil::split(val);
373
374
0
        if (vec.size() == 4)
375
0
        {
376
0
            return parse(vec[0], ret.r) && parse(vec[1], ret.g) && parse(vec[2], ret.b) &&
377
0
                   parse(vec[3], ret.a);
378
0
        }
379
0
        else if (vec.size() == 3)
380
0
        {
381
0
            ret.a = 1.0f;
382
0
            return parse(vec[0], ret.r) && parse(vec[1], ret.g) && parse(vec[2], ret.b);
383
0
        }
384
0
        else
385
0
        {
386
0
            return false;
387
0
        }
388
0
    }
389
    //-----------------------------------------------------------------------
390
    bool StringConverter::isNumber(const String& val)
391
0
    {
392
0
        char* end;
393
0
        strtod(val.c_str(), &end);
394
0
        return end == (val.c_str() + val.size());
395
0
    }
396
}
397
398