@@ -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
@@ -532,9 +533,30 @@ class LIBSCRATCHCPP_EXPORT Value
532
533
}
533
534
}
534
535
} else {
535
- if (v1.isString () || v2.isString ())
536
- return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
537
- else if (v1.isNumber () || v2.isNumber ())
536
+ if (v1.isString () || v2.isString ()) {
537
+ if (static_cast <int >(v1.m_type ) < 0 || static_cast <int >(v2.m_type ) < 0 )
538
+ return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
539
+
540
+ long l1, l2;
541
+ double d1, d2;
542
+ int type1 = checkString (v1.toString (), &l1, &d1);
543
+ int type2 = checkString (v2.toString (), &l2, &d2);
544
+
545
+ if (type1 == 1 )
546
+ d1 = l1;
547
+
548
+ if (type2 == 1 )
549
+ d2 = l2;
550
+
551
+ if (type1 > 0 && type2 > 0 )
552
+ return d1 == d2;
553
+ else if (type2 > 0 )
554
+ return v1.toString () == doubleToString (d2);
555
+ else if (type1 > 0 )
556
+ return doubleToString (d1) == v2.toString ();
557
+ else
558
+ return stringsEqual (v1.toUtf16 (), v2.toUtf16 ());
559
+ } else if (v1.isNumber () || v2.isNumber ())
538
560
return v1.toDouble () == v2.toDouble ();
539
561
else if (v1.isBool () || v2.isBool ())
540
562
return ((v1.m_type != Type::NaN && v2.m_type != Type::NaN) && (v1.toBool () == v2.toBool ()));
@@ -711,15 +733,37 @@ class LIBSCRATCHCPP_EXPORT Value
711
733
}
712
734
713
735
static const std::string digits = " 0123456789.eE+-" ;
714
- for (char c : s) {
736
+ const std::string *stringPtr = &s;
737
+ bool customStr = false ;
738
+
739
+ if (!s.empty () && ((s[0 ] == ' ' ) || (s.back () == ' ' ))) {
740
+ std::string *localPtr = new std::string (s);
741
+ stringPtr = localPtr;
742
+ customStr = true ;
743
+
744
+ while (!localPtr->empty () && (localPtr->at (0 ) == ' ' ))
745
+ localPtr->erase (0 , 1 );
746
+
747
+ while (!localPtr->empty () && (localPtr->back () == ' ' ))
748
+ localPtr->pop_back ();
749
+ }
750
+
751
+ for (char c : *stringPtr) {
715
752
if (digits.find (c) == std::string::npos) {
716
753
return 0 ;
717
754
}
718
755
}
756
+
719
757
try {
720
758
if (ok)
721
759
*ok = true ;
722
- return std::stod (s);
760
+
761
+ double ret = std::stod (*stringPtr);
762
+
763
+ if (customStr)
764
+ delete stringPtr;
765
+
766
+ return ret;
723
767
} catch (...) {
724
768
if (ok)
725
769
*ok = false ;
@@ -764,6 +808,28 @@ class LIBSCRATCHCPP_EXPORT Value
764
808
return 0 ;
765
809
}
766
810
}
811
+
812
+ static std::string doubleToString (double v)
813
+ {
814
+ std::stringstream stream;
815
+ stream << v;
816
+ std::string s = stream.str ();
817
+ std::size_t index;
818
+
819
+ for (int i = 0 ; i < 2 ; i++) {
820
+ if (i == 0 )
821
+ index = s.find (" e+" );
822
+ else
823
+ index = s.find (" e-" );
824
+
825
+ if (index != std::string::npos) {
826
+ while ((s.size () >= index + 3 ) && (s[index + 2 ] == ' 0' ))
827
+ s.erase (index + 2 , 1 );
828
+ }
829
+ }
830
+
831
+ return s;
832
+ }
767
833
};
768
834
769
835
} // namespace libscratchcpp
0 commit comments