@@ -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
@@ -532,9 +533,30 @@ class LIBSCRATCHCPP_EXPORT Value
532533 }
533534 }
534535 } 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 ())
538560 return v1.toDouble () == v2.toDouble ();
539561 else if (v1.isBool () || v2.isBool ())
540562 return ((v1.m_type != Type::NaN && v2.m_type != Type::NaN) && (v1.toBool () == v2.toBool ()));
@@ -711,15 +733,37 @@ class LIBSCRATCHCPP_EXPORT Value
711733 }
712734
713735 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) {
715752 if (digits.find (c) == std::string::npos) {
716753 return 0 ;
717754 }
718755 }
756+
719757 try {
720758 if (ok)
721759 *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;
723767 } catch (...) {
724768 if (ok)
725769 *ok = false ;
@@ -764,6 +808,28 @@ class LIBSCRATCHCPP_EXPORT Value
764808 return 0 ;
765809 }
766810 }
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+ }
767833};
768834
769835} // namespace libscratchcpp
0 commit comments