@@ -257,24 +257,7 @@ class LIBSCRATCHCPP_EXPORT Value
257257 case Type::Integer:
258258 return std::to_string (m_intValue);
259259 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);
278261 }
279262 case Type::Bool:
280263 return m_boolValue ? " true" : " false" ;
@@ -471,6 +454,26 @@ class LIBSCRATCHCPP_EXPORT Value
471454 std::string m_stringValue;
472455 };
473456
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+
474477 void initString (const std::string &str)
475478 {
476479 if (str.empty ())
@@ -486,23 +489,21 @@ class LIBSCRATCHCPP_EXPORT Value
486489 return ;
487490 }
488491
489- bool ok;
490- bool isLong = false ;
491492 long l;
492493 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 :
500498 *this = l;
501499 m_type = Type::Integer;
502- } else {
500+ break ;
501+ case 2 :
503502 *this = d;
504503 m_type = Type::Double;
505- }
504+ break ;
505+ default :
506+ break ;
506507 }
507508 }
508509
@@ -529,9 +530,30 @@ class LIBSCRATCHCPP_EXPORT Value
529530 }
530531 }
531532 } 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 ())
535557 return v1.toDouble () == v2.toDouble ();
536558 else if (v1.isBool () || v2.isBool ())
537559 return ((v1.m_type != Type::NaN && v2.m_type != Type::NaN) && (v1.toBool () == v2.toBool ()));
@@ -708,15 +730,37 @@ class LIBSCRATCHCPP_EXPORT Value
708730 }
709731
710732 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) {
712749 if (digits.find (c) == std::string::npos) {
713750 return 0 ;
714751 }
715752 }
753+
716754 try {
717755 if (ok)
718756 *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;
720764 } catch (...) {
721765 if (ok)
722766 *ok = false ;
@@ -761,6 +805,28 @@ class LIBSCRATCHCPP_EXPORT Value
761805 return 0 ;
762806 }
763807 }
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+ }
764830};
765831
766832} // namespace libscratchcpp
0 commit comments