@@ -257,24 +257,7 @@ class LIBSCRATCHCPP_EXPORT Value
257
257
case Type::Integer:
258
258
return std::to_string (m_intValue);
259
259
case Type::Double: {
260
- std::stringstream stream;
261
- stream << m_doubleValue;
262
- std::string s = stream.str ();
263
- std::size_t index;
264
-
265
- for (int i = 0 ; i < 2 ; i++) {
266
- if (i == 0 )
267
- index = s.find (" e+" );
268
- else
269
- index = s.find (" e-" );
270
-
271
- if (index != std::string::npos) {
272
- while ((s.size () >= index + 3 ) && (s[index + 2 ] == ' 0' ))
273
- s.erase (index + 2 , 1 );
274
- }
275
- }
276
-
277
- return s;
260
+ return doubleToString (m_doubleValue);
278
261
}
279
262
case Type::Bool:
280
263
return m_boolValue ? " true" : " false" ;
@@ -471,6 +454,26 @@ class LIBSCRATCHCPP_EXPORT Value
471
454
std::string m_stringValue;
472
455
};
473
456
457
+ // -1 - error
458
+ // 0 - is string
459
+ // 1 - is long
460
+ // 2 - is double
461
+ static int checkString (const std::string &str, long *longValue, double *doubleValue)
462
+ {
463
+ if (!longValue || !doubleValue)
464
+ return -1 ;
465
+
466
+ bool ok;
467
+
468
+ if ((str.find_first_of (' .' ) == std::string::npos) && (str.find_first_of (' e' ) == std::string::npos) && (str.find_first_of (' E' ) == std::string::npos)) {
469
+ *longValue = stringToLong (str, &ok);
470
+ return ok ? 1 : 0 ;
471
+ } else {
472
+ *doubleValue = stringToDouble (str, &ok);
473
+ return ok ? 2 : 0 ;
474
+ }
475
+ }
476
+
474
477
void initString (const std::string &str)
475
478
{
476
479
if (str.empty ())
@@ -486,23 +489,21 @@ class LIBSCRATCHCPP_EXPORT Value
486
489
return ;
487
490
}
488
491
489
- bool ok;
490
- bool isLong = false ;
491
492
long l;
492
493
double d;
493
- if ((str.find_first_of (' .' ) == std::string::npos) && (str.find_first_of (' e' ) == std::string::npos) && (str.find_first_of (' E' ) == std::string::npos)) {
494
- l = stringToLong (str, &ok);
495
- isLong = true ;
496
- } else
497
- d = stringToDouble (str, &ok);
498
- if (ok) {
499
- if (isLong) {
494
+ int type = checkString (str, &l, &d);
495
+
496
+ switch (type) {
497
+ case 1 :
500
498
*this = l;
501
499
m_type = Type::Integer;
502
- } else {
500
+ break ;
501
+ case 2 :
503
502
*this = d;
504
503
m_type = Type::Double;
505
- }
504
+ break ;
505
+ default :
506
+ break ;
506
507
}
507
508
}
508
509
@@ -529,9 +530,30 @@ class LIBSCRATCHCPP_EXPORT Value
529
530
}
530
531
}
531
532
} else {
532
- if (v1.isString () || v2.isString ())
533
- return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
534
- else if (v1.isNumber () || v2.isNumber ())
533
+ if (v1.isString () || v2.isString ()) {
534
+ if (static_cast <int >(v1.m_type ) < 0 || static_cast <int >(v2.m_type ) < 0 )
535
+ return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
536
+
537
+ long l1, l2;
538
+ double d1, d2;
539
+ int type1 = checkString (v1.toString (), &l1, &d1);
540
+ int type2 = checkString (v2.toString (), &l2, &d2);
541
+
542
+ if (type1 == 1 )
543
+ d1 = l1;
544
+
545
+ if (type2 == 1 )
546
+ d2 = l2;
547
+
548
+ if (type1 > 0 && type2 > 0 )
549
+ return d1 == d2;
550
+ else if (type2 > 0 )
551
+ return v1.toString () == doubleToString (d2);
552
+ else if (type1 > 0 )
553
+ return doubleToString (d1) == v2.toString ();
554
+ else
555
+ return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
556
+ } else if (v1.isNumber () || v2.isNumber ())
535
557
return v1.toDouble () == v2.toDouble ();
536
558
else if (v1.isBool () || v2.isBool ())
537
559
return ((v1.m_type != Type::NaN && v2.m_type != Type::NaN) && (v1.toBool () == v2.toBool ()));
@@ -708,15 +730,37 @@ class LIBSCRATCHCPP_EXPORT Value
708
730
}
709
731
710
732
static const std::string digits = " 0123456789.eE+-" ;
711
- for (char c : s) {
733
+ const std::string *stringPtr = &s;
734
+ bool customStr = false ;
735
+
736
+ if (!s.empty () && ((s[0 ] == ' ' ) || (s.back () == ' ' ))) {
737
+ std::string *localPtr = new std::string (s);
738
+ stringPtr = localPtr;
739
+ customStr = true ;
740
+
741
+ while (!localPtr->empty () && (localPtr->at (0 ) == ' ' ))
742
+ localPtr->erase (0 , 1 );
743
+
744
+ while (!localPtr->empty () && (localPtr->back () == ' ' ))
745
+ localPtr->pop_back ();
746
+ }
747
+
748
+ for (char c : *stringPtr) {
712
749
if (digits.find (c) == std::string::npos) {
713
750
return 0 ;
714
751
}
715
752
}
753
+
716
754
try {
717
755
if (ok)
718
756
*ok = true ;
719
- return std::stod (s);
757
+
758
+ double ret = std::stod (*stringPtr);
759
+
760
+ if (customStr)
761
+ delete stringPtr;
762
+
763
+ return ret;
720
764
} catch (...) {
721
765
if (ok)
722
766
*ok = false ;
@@ -761,6 +805,28 @@ class LIBSCRATCHCPP_EXPORT Value
761
805
return 0 ;
762
806
}
763
807
}
808
+
809
+ static std::string doubleToString (double v)
810
+ {
811
+ std::stringstream stream;
812
+ stream << v;
813
+ std::string s = stream.str ();
814
+ std::size_t index;
815
+
816
+ for (int i = 0 ; i < 2 ; i++) {
817
+ if (i == 0 )
818
+ index = s.find (" e+" );
819
+ else
820
+ index = s.find (" e-" );
821
+
822
+ if (index != std::string::npos) {
823
+ while ((s.size () >= index + 3 ) && (s[index + 2 ] == ' 0' ))
824
+ s.erase (index + 2 , 1 );
825
+ }
826
+ }
827
+
828
+ return s;
829
+ }
764
830
};
765
831
766
832
} // namespace libscratchcpp
0 commit comments