@@ -290,102 +290,108 @@ float OIIO_API strtof (const char *nptr, char **endptr, const std::locale& loc);
290
290
291
291
292
292
293
- // Helper template to test if a string is a generic type
294
- template <typename T>
295
- inline bool string_is (string_view /* s*/ ) {
296
- return false ; // Generic: assume there is an explicit specialization
297
- }
298
- // Special case for int
299
- template <> inline bool string_is<int > (string_view s) {
300
- if (s.empty ())
301
- return false ;
302
- char *endptr = 0 ;
303
- strtol (s.data (), &endptr, 10 );
304
- return (s.data () + s.size () == endptr);
305
- }
306
- // Special case for float. Note that by using Strutil::strtof, this always
307
- // treats '.' as the decimal character.
308
- template <> inline bool string_is<float > (string_view s) {
309
- if (s.empty ())
310
- return false ;
311
- char *endptr = 0 ;
312
- Strutil::strtof (s.data (), &endptr);
313
- return (s.data () + s.size () == endptr);
314
- }
315
-
316
-
317
-
318
293
// stoi() returns the int conversion of text from several string types.
319
294
// No exceptions or errors -- parsing errors just return 0.
320
- inline int stoi (const char * s) {
321
- return s && s[0 ] ? strtol (s, nullptr , 10 ) : 0 ;
322
- }
323
- inline int stoi (const std::string& s) { return Strutil::stoi (s.c_str ()); }
324
- inline int stoi (string_view s) { return Strutil::stoi (std::string (s)); }
325
-
295
+ OIIO_API int stoi (const char * s, size_t * pos=0 , int base=10 );
296
+ OIIO_API int stoi (const std::string& s, size_t * pos=0 , int base=10 );
297
+ OIIO_API int stoi (string_view s, size_t * pos=0 , int base=10 );
298
+ // N.B. For users of ustring, there's a stoi(ustring) defined in ustring.h.
326
299
327
300
328
301
// stoul() returns the unsigned int conversion of text from several string
329
302
// types. No exceptions or errors -- parsing errors just return 0.
330
- inline unsigned int stoul (const char * s) {
331
- return s && s[0 ] ? strtoul (s, nullptr , 10 ) : 0 ;
332
- }
333
- inline unsigned int stoul (const std::string& s) { return Strutil::stoul (s.c_str ()); }
334
- inline unsigned int stoul (string_view s) { return Strutil::stoul (std::string (s)); }
335
-
303
+ OIIO_API unsigned int stoul (const char * s, size_t * pos=0 , int base=10 );
304
+ OIIO_API unsigned int stoul (const std::string& s, size_t * pos=0 , int base=10 );
305
+ OIIO_API unsigned int stoul (string_view s, size_t * pos=0 , int base=10 );
306
+ // N.B. For users of ustring, there's a stoi(ustring) defined in ustring.h.
336
307
337
308
338
309
// / stof() returns the float conversion of text from several string types.
339
310
// / No exceptions or errors -- parsing errors just return 0.0. These always
340
311
// / use '.' for the decimal mark (versus atof and std::strtof, which are
341
312
// / locale-dependent).
342
- inline float stof (const std::string& s) {
343
- return s.size () ? Strutil::strtof (s.c_str (), nullptr ) : 0 .0f ;
344
- }
345
- inline float stof (const char * s) {
346
- return Strutil::strtof (s, nullptr );
347
- }
348
- inline float stof (string_view s) {
349
- return Strutil::strtof (std::string (s).c_str (), nullptr );
350
- }
313
+ OIIO_API float stof (const std::string& s, size_t * pos=0 );
314
+ OIIO_API float stof (const char * s, size_t * pos=0 );
315
+ OIIO_API float stof (string_view s, size_t * pos=0 );
316
+ // N.B. For users of ustring, there's a stof(ustring) defined in ustring.h.
351
317
352
318
// stof() version that takes an explicit locale (for example, if you pass a
353
319
// default-constructed std::locale, it will use the current native locale's
354
320
// decimal conventions).
355
- inline float stof (const std::string& s, const std::locale& loc) {
356
- return s.size () ? Strutil::strtof (s.c_str (), nullptr , loc) : 0 .0f ;
321
+ OIIO_API float stof (const std::string& s, const std::locale& loc, size_t * pos=0 );
322
+ OIIO_API float stof (const char * s, const std::locale& loc, size_t * pos=0 );
323
+ OIIO_API float stof (string_view s, const std::locale& loc, size_t * pos=0 );
324
+
325
+
326
+
327
+ // / Return true if the string is exactly (other than leading whitespace)
328
+ // / a valid int.
329
+ inline bool string_is_int (string_view s) {
330
+ size_t pos;
331
+ Strutil::stoi (s, &pos);
332
+ return pos && pos >= s.size (); // consumed the whole string
357
333
}
358
- inline float stof (const char * s, const std::locale& loc) {
359
- return Strutil::strtof (s, nullptr , loc);
334
+
335
+ // / Return true if the string is exactly (other than leading whitespace)
336
+ // / a valid float. This operations in a locale-independent manner, i.e.,
337
+ // / it assumes '.' as the decimal mark.
338
+ inline bool string_is_float (string_view s) {
339
+ size_t pos;
340
+ Strutil::stof (s, &pos);
341
+ return pos && pos >= s.size (); // consumed the whole string
360
342
}
361
- inline float stof (string_view s, const std::locale& loc) {
362
- return Strutil::strtof (std::string (s).c_str (), nullptr , loc);
343
+
344
+ // / Return true if the string is exactly (other than leading whitespace)
345
+ // / a valid float. This operations uses an explicit locale.
346
+ inline bool string_is_float (string_view s, const std::locale& loc) {
347
+ size_t pos;
348
+ Strutil::stof (s, loc, &pos);
349
+ return pos && pos >= s.size (); // consumed the whole string
363
350
}
364
351
365
352
366
353
367
354
// Helper template to convert from generic type to string (using default
368
- // locale).
355
+ // locale). Used when you want stoX but you're in a template.
369
356
template <typename T>
370
357
inline T from_string (string_view s) {
371
358
return T (s); // Generic: assume there is an explicit converter
372
359
}
373
360
// Special case for int
374
361
template <> inline int from_string<int > (string_view s) {
375
- return s. size () ? strtol (s. c_str (), nullptr , 10 ) : 0 ;
362
+ return Strutil::stoi (s) ;
376
363
}
377
364
// Special case for uint
378
365
template <> inline unsigned int from_string<unsigned int > (string_view s) {
379
- return s. size () ? strtoul (s. c_str (), nullptr , 10 ) : ( unsigned int ) 0 ;
366
+ return Strutil::stoul (s) ;
380
367
}
381
368
// Special case for float -- note that by using Strutil::strtof, this
382
369
// always treats '.' as the decimal mark.
383
370
template <> inline float from_string<float > (string_view s) {
384
- return s. size () ? Strutil::strtof (s. c_str (), nullptr ) : 0 . 0f ;
371
+ return Strutil::stof (s) ;
385
372
}
386
373
387
374
388
375
376
+ // Helper template to test if a string is a generic type. Used instead of
377
+ // string_is_X, but when you're inside templated code.
378
+ template <typename T>
379
+ inline bool string_is (string_view /* s*/ ) {
380
+ return false ; // Generic: assume there is an explicit specialization
381
+ }
382
+ // Special case for int
383
+ template <> inline bool string_is<int > (string_view s) {
384
+ return string_is_int (s);
385
+ }
386
+ // Special case for float. Note that by using Strutil::stof, this always
387
+ // treats '.' as the decimal character.
388
+ template <> inline bool string_is<float > (string_view s) {
389
+ return string_is_float (s);
390
+ }
391
+
392
+
393
+
394
+
389
395
// / Given a string containing values separated by a comma (or optionally
390
396
// / another separator), extract the individual values, placing them into
391
397
// / vals[] which is presumed to already contain defaults. If only a single
0 commit comments