diff --git a/src/db/db/dbBox.h b/src/db/db/dbBox.h index ea3e1648e..a3319fffb 100644 --- a/src/db/db/dbBox.h +++ b/src/db/db/dbBox.h @@ -860,8 +860,10 @@ template inline box & box::move (const vector &p) { - m_p1 += p; - m_p2 += p; + if (! empty ()) { + m_p1 += p; + m_p2 += p; + } return *this; } @@ -869,8 +871,10 @@ template inline box & box::enlarge (const vector &p) { - m_p1 -= p; - m_p2 += p; + if (! empty ()) { + m_p1 -= p; + m_p2 += p; + } return *this; } diff --git a/src/db/db/dbGDS2WriterBase.cc b/src/db/db/dbGDS2WriterBase.cc index cd6df2a99..d8dd26614 100644 --- a/src/db/db/dbGDS2WriterBase.cc +++ b/src/db/db/dbGDS2WriterBase.cc @@ -831,15 +831,8 @@ GDS2WriterBase::write_properties (const db::Layout &layout, db::properties_id_ty const tl::Variant &name = layout.properties_repository ().prop_name (p->first); long attr = -1; - if (name.is_long ()) { + if (name.can_convert_to_long ()) { attr = name.to_long (); - } else if (name.is_a_string ()) { - // string names representing a number are converted to numeric property names - tl::Extractor ex (name.to_string ()); - long a = 0; - if (ex.try_read (a) && ex.at_end ()) { - attr = a; - } } if (attr >= 0 && attr < 65535) { diff --git a/src/db/db/dbOASISWriter.cc b/src/db/db/dbOASISWriter.cc index ba2e2546e..4f41cde4b 100644 --- a/src/db/db/dbOASISWriter.cc +++ b/src/db/db/dbOASISWriter.cc @@ -55,7 +55,9 @@ make_gds_property (const tl::Variant &name) { // We write S_GDS_PROPERTY properties, because that is the only way to write properties // with numerical keys - return (name.is_long () && (name.to_long () < 0x8000 || name.to_long () >= 0)) || + return (name.is_longlong () && name.to_longlong () < 0x8000 && name.to_longlong () >= 0) || + (name.is_ulonglong () && name.to_ulonglong () < 0x8000) || + (name.is_long () && name.to_long () < 0x8000 && name.to_long () >= 0) || (name.is_ulong () && name.to_ulong () < 0x8000); } diff --git a/src/db/unit_tests/dbBox.cc b/src/db/unit_tests/dbBox.cc index 071d04ab5..5a3396c7b 100644 --- a/src/db/unit_tests/dbBox.cc +++ b/src/db/unit_tests/dbBox.cc @@ -41,12 +41,19 @@ TEST(2) EXPECT_EQ (b.moved (db::Vector (10, 20)), db::Box (110, 20, 10, 220)); EXPECT_EQ (b.enlarged (db::Vector (10, 20)), db::Box (-10, -20, 110, 220)); + EXPECT_EQ (empty.moved (db::Vector (10, 20)).empty (), true); + EXPECT_EQ (empty.enlarged (db::Vector (10, 20)).empty (), true); EXPECT_EQ (b + db::Box (-10, 20, 100, 200), db::Box (-10, 0, 100, 200)); EXPECT_EQ (b + db::Box (-10, -20, 100, -10), db::Box (-10, -20, 100, 200)); EXPECT_EQ (b + db::Box (110, 220, 120, 250), db::Box (0, 0, 120, 250)); EXPECT_EQ (b & db::Box (110, 220, 120, 250), empty); EXPECT_EQ (b & db::Box (50, 100, 120, 250), db::Box (50, 100, 100, 200)); EXPECT_EQ (b & db::Box (50, 100, 60, 120), db::Box (50, 100, 60, 120)); + + empty.move (db::Vector (10, 20)); + EXPECT_EQ (empty == db::Box (), true); + empty.enlarge (db::Vector (10, 20)); + EXPECT_EQ (empty == db::Box (), true); } TEST(3) diff --git a/src/tl/tl/tlString.cc b/src/tl/tl/tlString.cc index 52d7f6715..aaf8ab3a0 100644 --- a/src/tl/tl/tlString.cc +++ b/src/tl/tl/tlString.cc @@ -831,186 +831,160 @@ tl::Extractor::read_quoted (std::string &value) return *this; } -bool +namespace +{ + template struct overflow_msg_func; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on long long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned long long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned integer")); + } + }; +} + +template bool +tl::Extractor::try_read_signed_int (T &value) +{ + if (! *skip ()) { + return false; + } + + bool minus = false; + if (*m_cp == '-') { + minus = true; + ++m_cp; + } else if (*m_cp == '+') { + ++m_cp; + } + + if (! isdigit (*m_cp)) { + return false; + } + + value = 0; + while (isdigit (*m_cp)) { + if (value > std::numeric_limits::max () / 10) { + throw tl::Exception (overflow_msg_func () ()); + } + value *= 10; + if (value > std::numeric_limits::max () - (*m_cp - '0')) { + throw tl::Exception (overflow_msg_func () ()); + } + value += (*m_cp - '0'); + ++m_cp; + } + + if (minus) { + value = -value; + } + + return true; +} + +template bool +tl::Extractor::try_read_unsigned_int (T &value) +{ + if (! *skip ()) { + return false; + } + + if (! isdigit (*m_cp)) { + return false; + } + + value = 0; + while (isdigit (*m_cp)) { + if (value > std::numeric_limits::max () / 10) { + throw tl::Exception (overflow_msg_func () ()); + } + value *= 10; + if (value > std::numeric_limits::max () - (*m_cp - '0')) { + throw tl::Exception (overflow_msg_func () ()); + } + value += (*m_cp - '0'); + ++m_cp; + } + + return true; +} + +bool tl::Extractor::try_read (unsigned int &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool -tl::Extractor::try_read (int &value) -{ - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; -} - -bool +bool tl::Extractor::try_read (unsigned long &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool +bool tl::Extractor::try_read (unsigned long long &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned long long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool +bool +tl::Extractor::try_read (int &value) +{ + return try_read_signed_int (value); +} + +bool tl::Extractor::try_read (long &value) { - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; + return try_read_signed_int (value); } -bool +bool tl::Extractor::try_read (long long &value) { - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on long long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; + return try_read_signed_int (value); } - bool tl::Extractor::try_read (double &value) { diff --git a/src/tl/tl/tlString.h b/src/tl/tl/tlString.h index 718b2c169..11c8b05a4 100644 --- a/src/tl/tl/tlString.h +++ b/src/tl/tl/tlString.h @@ -732,6 +732,9 @@ public: } private: + template bool try_read_signed_int (T &value); + template bool try_read_unsigned_int (T &value); + const char *m_cp; std::string m_str; }; diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index d223ab537..322e17820 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -894,18 +894,18 @@ normalized_type (Variant::type type) case Variant::t_short: case Variant::t_int: case Variant::t_long: - return Variant::t_long; + case Variant::t_longlong: + return Variant::t_longlong; case Variant::t_uchar: case Variant::t_ushort: case Variant::t_uint: case Variant::t_ulong: - return Variant::t_ulong; + case Variant::t_ulonglong: + return Variant::t_ulonglong; case Variant::t_stdstring: case Variant::t_string: return Variant::t_string; default: - case Variant::t_longlong: - case Variant::t_ulonglong: #if defined(HAVE_64BIT_COORD) case Variant::t_int128: #endif @@ -1195,8 +1195,12 @@ Variant::can_convert_to_ulonglong () const case t_stdstring: { tl::Extractor ex (to_string ()); - unsigned long long ll; - return ex.try_read (ll) && ex.at_end (); + try { + unsigned long long ll; + return ex.try_read (ll) && ex.at_end (); + } catch (...) { + return false; + } } default: return false; @@ -1236,8 +1240,12 @@ Variant::can_convert_to_longlong () const case t_stdstring: { tl::Extractor ex (to_string ()); - long long ll; - return ex.try_read (ll) && ex.at_end (); + try { + long long ll; + return ex.try_read (ll) && ex.at_end (); + } catch (...) { + return false; + } } default: return false; @@ -1257,9 +1265,9 @@ Variant::can_convert_to_ulong () const return m_var.m_int128 <= __int128 (std::numeric_limits::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits::min ()); #endif case t_longlong: - return m_var.m_longlong >= 0 && m_var.m_longlong < (long long) std::numeric_limits::max (); + return m_var.m_longlong >= 0 && (unsigned long long) m_var.m_longlong <= (unsigned long long) std::numeric_limits::max (); case t_ulonglong: - return m_var.m_ulonglong < (unsigned long long) std::numeric_limits::max (); + return m_var.m_ulonglong <= (unsigned long long) std::numeric_limits::max (); case t_ulong: case t_bool: case t_uchar: @@ -1283,8 +1291,12 @@ Variant::can_convert_to_ulong () const case t_stdstring: { tl::Extractor ex (to_string ()); - unsigned long l; - return ex.try_read (l) && ex.at_end (); + try { + unsigned long l; + return ex.try_read (l) && ex.at_end (); + } catch (...) { + return false; + } } default: return false; @@ -1326,8 +1338,12 @@ Variant::can_convert_to_long () const case t_stdstring: { tl::Extractor ex (to_string ()); - long l; - return ex.try_read (l) && ex.at_end (); + try { + long l; + return ex.try_read (l) && ex.at_end (); + } catch (...) { + return false; + } } default: return false; @@ -1371,8 +1387,12 @@ Variant::can_convert_to_int () const case t_stdstring: { tl::Extractor ex (to_string ()); - long l; - return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits::min () && l <= (long) std::numeric_limits::max (); + try { + long l; + return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits::min () && l <= (long) std::numeric_limits::max (); + } catch (...) { + return false; + } } default: return false; @@ -1416,8 +1436,12 @@ Variant::can_convert_to_uint () const case t_stdstring: { tl::Extractor ex (to_string ()); - long l; - return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits::min () && l <= (long) std::numeric_limits::max (); + try { + long l; + return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits::min () && l <= (long) std::numeric_limits::max (); + } catch (...) { + return false; + } } default: return false; @@ -1684,7 +1708,7 @@ Variant::to_ulonglong () const return m_var.m_long; #if defined(HAVE_64BIT_COORD) } else if (m_type == t_int128) { - return m_var.m_int128; + return (unsigned long long) m_var.m_int128; #endif } else if (m_type == t_ulonglong) { return m_var.m_ulonglong; @@ -1738,7 +1762,7 @@ Variant::to_longlong () const return m_var.m_longlong; #if defined(HAVE_64BIT_COORD) } else if (m_type == t_int128) { - return m_var.m_int128; + return (long long) m_var.m_int128; #endif } else if (m_type == t_bool) { return m_var.m_bool; @@ -1783,12 +1807,12 @@ Variant::to_ulong () const } else if (m_type == t_long) { return m_var.m_long; } else if (m_type == t_ulonglong) { - return m_var.m_ulonglong; + return (unsigned long) (m_var.m_ulonglong); } else if (m_type == t_longlong) { - return m_var.m_longlong; + return (unsigned long) (m_var.m_longlong); #if defined(HAVE_64BIT_COORD) } else if (m_type == t_int128) { - return m_var.m_int128; + return (unsigned long) (m_var.m_int128); #endif } else if (m_type == t_bool) { return m_var.m_bool; @@ -1833,12 +1857,12 @@ Variant::to_long () const } else if (m_type == t_long) { return m_var.m_long; } else if (m_type == t_ulonglong) { - return m_var.m_ulonglong; + return long (m_var.m_ulonglong); } else if (m_type == t_longlong) { - return m_var.m_longlong; + return long (m_var.m_longlong); #if defined(HAVE_64BIT_COORD) } else if (m_type == t_int128) { - return m_var.m_int128; + return long (m_var.m_int128); #endif } else if (m_type == t_bool) { return m_var.m_bool; diff --git a/src/tl/unit_tests/tlVariant.cc b/src/tl/unit_tests/tlVariant.cc index 6fa511411..5a8b688d7 100644 --- a/src/tl/unit_tests/tlVariant.cc +++ b/src/tl/unit_tests/tlVariant.cc @@ -113,7 +113,9 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_char (), false); EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "nil"); vv = v; @@ -135,10 +137,13 @@ TEST(1) EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_ulong (), true); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "#u1"); EXPECT_EQ (v.to_long (), 1l); + EXPECT_EQ (v.to_longlong (), 1l); EXPECT_EQ (v.is (), true); EXPECT_EQ (v.is (), false); EXPECT_EQ (vv == v, false); @@ -167,11 +172,14 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_ulong (), true); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "#u2"); EXPECT_EQ (v.to_long (), 2l); + EXPECT_EQ (v.to_longlong (), 2l); EXPECT_EQ (vv == v, false); EXPECT_EQ (vv != v, true); vv = v; @@ -194,7 +202,9 @@ TEST(1) EXPECT_EQ (v.is_list (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_long (), true); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), true); @@ -202,6 +212,7 @@ TEST(1) EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "#1"); EXPECT_EQ (v.to_long (), 1l); + EXPECT_EQ (v.to_longlong (), 1l); EXPECT_EQ (vv == v, false); EXPECT_EQ (vv != v, true); vv = v; @@ -239,6 +250,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.to_parsable_string (), "#2"); EXPECT_EQ (v.to_long (), 2l); + EXPECT_EQ (v.to_longlong (), 2l); EXPECT_EQ (v.to_double (), 2.0); EXPECT_EQ (v.to_float (), 2.0); EXPECT_EQ (vv == v, false); @@ -261,7 +273,9 @@ TEST(1) EXPECT_EQ (v.is_list (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_char (), false); EXPECT_EQ (v.is_double (), true); EXPECT_EQ (v.is (), false); @@ -278,6 +292,10 @@ TEST(1) EXPECT_EQ (v.to_parsable_string (), "##5"); EXPECT_EQ (v.to_double (), 5.0); EXPECT_EQ (v.to_float (), 5.0); + EXPECT_EQ (v.to_long (), 5); + EXPECT_EQ (v.to_ulong (), 5u); + EXPECT_EQ (v.to_longlong (), 5); + EXPECT_EQ (v.to_ulonglong (), 5u); EXPECT_EQ (vv == v, false); EXPECT_EQ (vv != v, true); vv = v; @@ -300,7 +318,9 @@ TEST(1) EXPECT_EQ (v.is_list (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), true); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); @@ -317,6 +337,10 @@ TEST(1) EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.to_parsable_string (), "##5"); EXPECT_EQ (v.to_double (), 5.0); + EXPECT_EQ (v.to_long (), 5); + EXPECT_EQ (v.to_longlong (), 5); + EXPECT_EQ (v.to_ulong (), 5u); + EXPECT_EQ (v.to_ulonglong (), 5u); EXPECT_EQ (*(double *)v.native_ptr (), 5.0); EXPECT_EQ (vv == v, true); EXPECT_EQ (vv != v, false); @@ -365,6 +389,8 @@ TEST(1) EXPECT_EQ (v.is_char (), false); EXPECT_EQ (v.is_long (), true); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_longlong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "#2"); vv = v; @@ -440,6 +466,8 @@ TEST(1) EXPECT_EQ (v.is_cstring (), true); EXPECT_EQ (v.is_long (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_longlong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.to_parsable_string (), "'hal\\'l\"o'"); @@ -470,6 +498,8 @@ TEST(1) EXPECT_EQ (v.is_stdstring (), false); EXPECT_EQ (v.is_long (), false); EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_longlong (), false); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (std::string (v.to_string ()), "hal'l\"o"); @@ -810,6 +840,217 @@ TEST(3) EXPECT_EQ (v2 < v2, false); } +// can_convert_to +TEST(4) +{ + tl::Variant v; + v = tl::Variant (1); + EXPECT_EQ (v.can_convert_to_char (), true); + EXPECT_EQ (v.can_convert_to_uchar (), true); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), true); + EXPECT_EQ (v.can_convert_to_ushort (), true); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), true); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant (-1); + EXPECT_EQ (v.can_convert_to_char (), true); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), true); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), false); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), false); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), false); + + v = tl::Variant (1000); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), true); + EXPECT_EQ (v.can_convert_to_ushort (), true); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), true); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant ("1000"); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), true); + EXPECT_EQ (v.can_convert_to_ushort (), true); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), true); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant (100000); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), true); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant (10000000000ll); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), false); + EXPECT_EQ (v.can_convert_to_uint (), false); + if (sizeof (long) == 4) { + EXPECT_EQ (v.can_convert_to_long (), false); + EXPECT_EQ (v.can_convert_to_ulong (), false); + } else { + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + } + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant (0.5); + EXPECT_EQ (v.can_convert_to_char (), true); + EXPECT_EQ (v.can_convert_to_uchar (), true); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), true); + EXPECT_EQ (v.can_convert_to_ushort (), true); + EXPECT_EQ (v.can_convert_to_int (), true); + EXPECT_EQ (v.can_convert_to_uint (), true); + EXPECT_EQ (v.can_convert_to_long (), true); + EXPECT_EQ (v.can_convert_to_ulong (), true); + EXPECT_EQ (v.can_convert_to_longlong (), true); + EXPECT_EQ (v.can_convert_to_ulonglong (), true); + + v = tl::Variant ("100000000000000000000"); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), true); + EXPECT_EQ (v.can_convert_to_float (), true); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), false); + EXPECT_EQ (v.can_convert_to_uint (), false); + EXPECT_EQ (v.can_convert_to_long (), false); + EXPECT_EQ (v.can_convert_to_ulong (), false); + EXPECT_EQ (v.can_convert_to_longlong (), false); + EXPECT_EQ (v.can_convert_to_ulonglong (), false); + + v = tl::Variant ("1000x"); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), false); + EXPECT_EQ (v.can_convert_to_float (), false); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), false); + EXPECT_EQ (v.can_convert_to_uint (), false); + EXPECT_EQ (v.can_convert_to_long (), false); + EXPECT_EQ (v.can_convert_to_ulong (), false); + EXPECT_EQ (v.can_convert_to_longlong (), false); + EXPECT_EQ (v.can_convert_to_ulonglong (), false); + + v = tl::Variant (""); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), false); + EXPECT_EQ (v.can_convert_to_float (), false); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), false); + EXPECT_EQ (v.can_convert_to_uint (), false); + EXPECT_EQ (v.can_convert_to_long (), false); + EXPECT_EQ (v.can_convert_to_ulong (), false); + EXPECT_EQ (v.can_convert_to_longlong (), false); + EXPECT_EQ (v.can_convert_to_ulonglong (), false); + + v = tl::Variant ("x"); + EXPECT_EQ (v.can_convert_to_char (), false); + EXPECT_EQ (v.can_convert_to_uchar (), false); + EXPECT_EQ (v.can_convert_to_double (), false); + EXPECT_EQ (v.can_convert_to_float (), false); + EXPECT_EQ (v.can_convert_to_short (), false); + EXPECT_EQ (v.can_convert_to_ushort (), false); + EXPECT_EQ (v.can_convert_to_int (), false); + EXPECT_EQ (v.can_convert_to_uint (), false); + EXPECT_EQ (v.can_convert_to_long (), false); + EXPECT_EQ (v.can_convert_to_ulong (), false); + EXPECT_EQ (v.can_convert_to_longlong (), false); + EXPECT_EQ (v.can_convert_to_ulonglong (), false); +} + +// Variants as key maps +TEST(5) +{ + std::map m; + + // there are four categories which are separated: + // int + // unsigned int + // float (downwards compatible with int and unsigned int) + // string + m.insert (std::make_pair (tl::Variant (1), 17)); + m.insert (std::make_pair (tl::Variant ((unsigned int) 2), 42)); + m.insert (std::make_pair (tl::Variant ("3"), 41)); + m.insert (std::make_pair (tl::Variant (2.5), -17)); + + // int category + EXPECT_EQ (m [1], 17); + EXPECT_EQ (m [(char) 1], 17); + EXPECT_EQ (m [(short) 1], 17); + EXPECT_EQ (m [(int) 1], 17); + EXPECT_EQ (m [(long long) 1], 17); + EXPECT_EQ (m [1.0], 17); + // non-members of that category + EXPECT_EQ (m [1.25], 0); + EXPECT_EQ (m [(unsigned int) 1], 0); + EXPECT_EQ (m ["1"], 0); + + // unsigned int category + EXPECT_EQ (m [(unsigned char) 2], 42); + EXPECT_EQ (m [(unsigned short) 2], 42); + EXPECT_EQ (m [(unsigned int) 2], 42); + EXPECT_EQ (m [(unsigned long long) 2], 42); + EXPECT_EQ (m [2.0], 42); + // non-members of that category + EXPECT_EQ (m [2.25], 0); + EXPECT_EQ (m [2], 0); + EXPECT_EQ (m ["2"], 0); + + // float category + EXPECT_EQ (m [2.5], -17); + EXPECT_EQ (m [2.5001], 0); + + // string category + EXPECT_EQ (m ["3"], 41); + EXPECT_EQ (m [" 3"], 0); +} + } diff --git a/testdata/python/dbLayoutTest.py b/testdata/python/dbLayoutTest.py index b9baad341..4377479f8 100644 --- a/testdata/python/dbLayoutTest.py +++ b/testdata/python/dbLayoutTest.py @@ -19,6 +19,7 @@ import pya import unittest import sys +import os class DBLayoutTest(unittest.TestCase): @@ -1104,6 +1105,53 @@ class DBLayoutTest(unittest.TestCase): ly._destroy() + # Bug #109 + def test_bug109(self): + + testtmp = os.getenv("TESTTMP_WITH_NAME", os.getenv("TESTTMP", ".")) + + file_gds = os.path.join(testtmp, "bug109.gds") + file_oas = os.path.join(testtmp, "bug109.oas") + + ly = pya.Layout() + top = ly.create_cell("TOP") + l1 = ly.layer(1, 0) + shape = top.shapes(l1).insert(pya.Box(0, 10, 20, 30)) + shape.set_property(2, "hello, world") + shape.set_property("42", "the answer") + + ly.write(file_gds) + ly.write(file_oas) + + ly2 = pya.Layout() + ly2.read(file_gds) + l2 = ly2.layer(1, 0) + shape = None + for s in ly2.top_cell().shapes(l2).each(): + shape = s + self.assertEqual(shape.property(2), "hello, world") + self.assertEqual(shape.property("2"), None) + self.assertEqual(shape.property(2.0), "hello, world") + self.assertEqual(shape.property(22), None) + self.assertEqual(shape.property(42), "the answer") + self.assertEqual(shape.property("42"), None) + self.assertEqual(shape.property(42.0), "the answer") + + ly2 = pya.Layout() + ly2.read(file_oas) + l2 = ly2.layer(1, 0) + shape = None + for s in ly2.top_cell().shapes(l2).each(): + shape = s + self.assertEqual(shape.property(2), "hello, world") + self.assertEqual(shape.property("2"), None) + self.assertEqual(shape.property(2.0), "hello, world") + self.assertEqual(shape.property(22), None) + self.assertEqual(shape.property("42"), "the answer") + self.assertEqual(shape.property(42), None) + self.assertEqual(shape.property(42.0), None) + + # run unit tests if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(DBLayoutTest)