gnu: Add sajson-for-gemmi.
* gnu/packages/cpp.scm (sajson-for-gemmi): New variable. Signed-off-by: Liliana Marie Prikler <liliana.prikler@gmail.com>master
parent
fd4342728d
commit
3cbb634a89
|
@ -27,6 +27,7 @@
|
|||
#:use-module (guix utils)
|
||||
#:use-module ((guix licenses) #:prefix license:)
|
||||
#:use-module (guix download)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix git-download)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu packages algebra)
|
||||
|
@ -35,6 +36,7 @@
|
|||
#:use-module (gnu packages boost)
|
||||
#:use-module (gnu packages check)
|
||||
#:use-module (gnu packages compression)
|
||||
#:use-module (gnu packages cpp)
|
||||
#:use-module (gnu packages documentation)
|
||||
#:use-module (gnu packages fontutils)
|
||||
#:use-module (gnu packages gl)
|
||||
|
@ -50,8 +52,10 @@
|
|||
#:use-module (gnu packages qt)
|
||||
#:use-module (gnu packages serialization)
|
||||
#:use-module (gnu packages sphinx)
|
||||
#:use-module (gnu packages stb)
|
||||
#:use-module (gnu packages xml)
|
||||
#:use-module (guix build-system cmake)
|
||||
#:use-module (guix build-system copy)
|
||||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix build-system python))
|
||||
|
||||
|
|
|
@ -2102,6 +2102,22 @@ different floating point sizes and complex transformations.")
|
|||
parsing with only a single memory allocation.")
|
||||
(license license:expat))))
|
||||
|
||||
(define-public sajson-for-gemmi
|
||||
(package/inherit sajson
|
||||
(name "sajson-for-gemmi")
|
||||
(source (origin
|
||||
(inherit (package-source sajson))
|
||||
(patches (cons
|
||||
(search-patch
|
||||
"sajson-for-gemmi-numbers-as-strings.patch")
|
||||
(origin-patches (package-source sajson))))))
|
||||
(arguments
|
||||
(substitute-keyword-arguments (package-arguments sajson)
|
||||
;; This is a modified version used in gemmi, in which numbers are kept
|
||||
;; as strings. Building the tests fails with the modification.
|
||||
((#:tests? _ #f) #f)))
|
||||
(properties '((hidden? . #t)))))
|
||||
|
||||
(define-public optionparser
|
||||
(package
|
||||
(name "optionparser")
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
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);
|
||||
}
|
||||
}
|
Reference in New Issue