* gnu/packages/cpp.scm (sajson-for-gemmi): New variable. Signed-off-by: Liliana Marie Prikler <liliana.prikler@gmail.com>
		
			
				
	
	
		
			195 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
Patch for gemmi: Keep numbers in JSON file as strings.
 | 
						|
 | 
						|
Adapted from this commit of the bundled fork of sajson in gemmi:
 | 
						|
https://github.com/project-gemmi/gemmi/commit/fccbca4f6040364ba708613e1429c2251872240d
 | 
						|
 | 
						|
diff -ur a/include/sajson.h b/include/sajson.h
 | 
						|
--- a/include/sajson.h
 | 
						|
+++ b/include/sajson.h
 | 
						|
@@ -411,43 +411,6 @@
 | 
						|
 };
 | 
						|
 } // namespace internal
 | 
						|
 
 | 
						|
-namespace integer_storage {
 | 
						|
-enum { word_length = 1 };
 | 
						|
-
 | 
						|
-inline int load(const size_t* location) {
 | 
						|
-    int value;
 | 
						|
-    memcpy(&value, location, sizeof(value));
 | 
						|
-    return value;
 | 
						|
-}
 | 
						|
-
 | 
						|
-inline void store(size_t* location, int value) {
 | 
						|
-    // NOTE: Most modern compilers optimize away this constant-size
 | 
						|
-    // memcpy into a single instruction. If any don't, and treat
 | 
						|
-    // punning through a union as legal, they can be special-cased.
 | 
						|
-    static_assert(
 | 
						|
-        sizeof(value) <= sizeof(*location),
 | 
						|
-        "size_t must not be smaller than int");
 | 
						|
-    memcpy(location, &value, sizeof(value));
 | 
						|
-}
 | 
						|
-} // namespace integer_storage
 | 
						|
-
 | 
						|
-namespace double_storage {
 | 
						|
-enum { word_length = sizeof(double) / sizeof(size_t) };
 | 
						|
-
 | 
						|
-inline double load(const size_t* location) {
 | 
						|
-    double value;
 | 
						|
-    memcpy(&value, location, sizeof(double));
 | 
						|
-    return value;
 | 
						|
-}
 | 
						|
-
 | 
						|
-inline void store(size_t* location, double value) {
 | 
						|
-    // NOTE: Most modern compilers optimize away this constant-size
 | 
						|
-    // memcpy into a single instruction. If any don't, and treat
 | 
						|
-    // punning through a union as legal, they can be special-cased.
 | 
						|
-    memcpy(location, &value, sizeof(double));
 | 
						|
-}
 | 
						|
-} // namespace double_storage
 | 
						|
-
 | 
						|
 /// Represents a JSON value.  First, call get_type() to check its type,
 | 
						|
 /// which determines which methods are available.
 | 
						|
 ///
 | 
						|
@@ -585,70 +548,10 @@
 | 
						|
         return length;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    /// If a numeric value was parsed as a 32-bit integer, returns it.
 | 
						|
-    /// Only legal if get_type() is TYPE_INTEGER.
 | 
						|
-    int get_integer_value() const {
 | 
						|
-        assert_tag(tag::integer);
 | 
						|
-        return integer_storage::load(payload);
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    /// If a numeric value was parsed as a double, returns it.
 | 
						|
-    /// Only legal if get_type() is TYPE_DOUBLE.
 | 
						|
-    double get_double_value() const {
 | 
						|
-        assert_tag(tag::double_);
 | 
						|
-        return double_storage::load(payload);
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    /// Returns a numeric value as a double-precision float.
 | 
						|
-    /// Only legal if get_type() is TYPE_INTEGER or TYPE_DOUBLE.
 | 
						|
-    double get_number_value() const {
 | 
						|
-        assert_tag_2(tag::integer, tag::double_);
 | 
						|
-        if (value_tag == tag::integer) {
 | 
						|
-            return get_integer_value();
 | 
						|
-        } else {
 | 
						|
-            return get_double_value();
 | 
						|
-        }
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    /// Returns true and writes to the output argument if the numeric value
 | 
						|
-    /// fits in a 53-bit integer.  This is useful for timestamps and other
 | 
						|
-    /// situations where integral values with greater than 32-bit precision
 | 
						|
-    /// are used, as 64-bit values are not understood by all JSON
 | 
						|
-    /// implementations or languages.
 | 
						|
-    /// Returns false if the value is not an integer or not in range.
 | 
						|
-    /// Only legal if get_type() is TYPE_INTEGER or TYPE_DOUBLE.
 | 
						|
-    bool get_int53_value(int64_t* out) const {
 | 
						|
-        // Make sure the output variable is always defined to avoid any
 | 
						|
-        // possible situation like
 | 
						|
-        // https://gist.github.com/chadaustin/2c249cb850619ddec05b23ca42cf7a18
 | 
						|
-        *out = 0;
 | 
						|
-
 | 
						|
-        assert_tag_2(tag::integer, tag::double_);
 | 
						|
-        switch (value_tag) {
 | 
						|
-        case tag::integer:
 | 
						|
-            *out = get_integer_value();
 | 
						|
-            return true;
 | 
						|
-        case tag::double_: {
 | 
						|
-            double v = get_double_value();
 | 
						|
-            if (v < -(1LL << 53) || v > (1LL << 53)) {
 | 
						|
-                return false;
 | 
						|
-            }
 | 
						|
-            int64_t as_int = static_cast<int64_t>(v);
 | 
						|
-            if (as_int != v) {
 | 
						|
-                return false;
 | 
						|
-            }
 | 
						|
-            *out = as_int;
 | 
						|
-            return true;
 | 
						|
-        }
 | 
						|
-        default:
 | 
						|
-            return false;
 | 
						|
-        }
 | 
						|
-    }
 | 
						|
-
 | 
						|
     /// Returns the length of the string.
 | 
						|
     /// Only legal if get_type() is TYPE_STRING.
 | 
						|
     size_t get_string_length() const {
 | 
						|
-        assert_tag(tag::string);
 | 
						|
+        assert_tag_3(tag::string, tag::integer, tag::double_);
 | 
						|
         return payload[1] - payload[0];
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -659,7 +562,7 @@
 | 
						|
     /// embedded NULs.
 | 
						|
     /// Only legal if get_type() is TYPE_STRING.
 | 
						|
     const char* as_cstring() const {
 | 
						|
-        assert_tag(tag::string);
 | 
						|
+        assert_tag_3(tag::string, tag::integer, tag::double_);
 | 
						|
         return text + payload[0];
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -667,7 +570,7 @@
 | 
						|
     /// Returns a string's value as a std::string.
 | 
						|
     /// Only legal if get_type() is TYPE_STRING.
 | 
						|
     std::string as_string() const {
 | 
						|
-        assert_tag(tag::string);
 | 
						|
+        assert_tag_3(tag::string, tag::integer, tag::double_);
 | 
						|
         return std::string(text + payload[0], text + payload[1]);
 | 
						|
     }
 | 
						|
 #endif
 | 
						|
@@ -690,6 +593,10 @@
 | 
						|
         assert(e1 == value_tag || e2 == value_tag);
 | 
						|
     }
 | 
						|
 
 | 
						|
+    void assert_tag_3(tag e1, tag e2, tag e3) const {
 | 
						|
+        assert(e1 == value_tag || e2 == value_tag || e3 == value_tag);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     void assert_in_bounds(size_t i) const { assert(i < get_length()); }
 | 
						|
 
 | 
						|
     const tag value_tag;
 | 
						|
@@ -2059,6 +1966,8 @@
 | 
						|
     std::pair<char*, internal::tag> parse_number(char* p) {
 | 
						|
         using internal::tag;
 | 
						|
 
 | 
						|
+	size_t start = p - input.get_data();
 | 
						|
+
 | 
						|
         // Assume 32-bit, two's complement integers.
 | 
						|
         static constexpr unsigned RISKY = INT_MAX / 10u;
 | 
						|
         unsigned max_digit_after_risky = INT_MAX % 10u;
 | 
						|
@@ -2235,23 +2144,18 @@
 | 
						|
                 u = 0u - u;
 | 
						|
             }
 | 
						|
         }
 | 
						|
+
 | 
						|
+        bool success;
 | 
						|
+        size_t* out = allocator.reserve(2, &success);
 | 
						|
+        if (SAJSON_UNLIKELY(!success)) {
 | 
						|
+            return std::make_pair(oom(p, "number"), tag::null);
 | 
						|
+        }
 | 
						|
+        out[0] = start;
 | 
						|
+        out[1] = p - input.get_data();
 | 
						|
+
 | 
						|
         if (try_double) {
 | 
						|
-            bool success;
 | 
						|
-            size_t* out
 | 
						|
-                = allocator.reserve(double_storage::word_length, &success);
 | 
						|
-            if (SAJSON_UNLIKELY(!success)) {
 | 
						|
-                return std::make_pair(oom(p, "double"), tag::null);
 | 
						|
-            }
 | 
						|
-            double_storage::store(out, d);
 | 
						|
             return std::make_pair(p, tag::double_);
 | 
						|
         } else {
 | 
						|
-            bool success;
 | 
						|
-            size_t* out
 | 
						|
-                = allocator.reserve(integer_storage::word_length, &success);
 | 
						|
-            if (SAJSON_UNLIKELY(!success)) {
 | 
						|
-                return std::make_pair(oom(p, "integer"), tag::null);
 | 
						|
-            }
 | 
						|
-            integer_storage::store(out, static_cast<int>(u));
 | 
						|
             return std::make_pair(p, tag::integer);
 | 
						|
         }
 | 
						|
     }
 |