Message ID | 20221007152148.32591-4-david.elsing@posteo.net |
---|---|
State | Accepted |
Headers | show |
Series | None | expand |
Am Freitag, dem 07.10.2022 um 15:21 +0000 schrieb David Elsing: > * gnu/packages/cpp.scm (sajson): New variable. > --- > gnu/packages/cpp.scm | 60 > +++++++++++++++++++ > .../patches/sajson-build-with-gcc10.patch | 45 ++++++++++++++ > 2 files changed, 105 insertions(+) > create mode 100644 gnu/packages/patches/sajson-build-with- > gcc10.patch > > diff --git a/gnu/packages/cpp.scm b/gnu/packages/cpp.scm > index 38a2a9e829..dca0245df5 100644 > --- a/gnu/packages/cpp.scm > +++ b/gnu/packages/cpp.scm > @@ -57,6 +57,7 @@ (define-module (gnu packages cpp) > #:use-module (guix build-system gnu) > #:use-module (guix build-system meson) > #:use-module (guix build-system python) > + #:use-module (guix build-system scons) > #:use-module (guix modules) > #:use-module (guix gexp) > #:use-module (gnu packages) > @@ -2005,3 +2006,62 @@ (define-public pocketfft-cpp > computing Fast Fourier transformations. It supports > multidimensional arrays, > different floating point sizes and complex transformations.") > (license license:bsd-3)))) > + > +(define-public sajson > + (let ((commit "ec644013e34f9984a3cc9ba568cab97a391db9cd") > + (revision "0")) > + (package > + (name "sajson") > + (version (git-version "1.0" revision commit)) > + (source (origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/chadaustin/sajson") > + (commit commit))) > + (file-name (git-file-name name version)) > + (patches > + (search-patches "sajson-build-with-gcc10.patch")) > + (sha256 > + (base32 > + > "0fjag27w7gvkc5pdhq3ad7yc09rabpzahndw1sgsg04ipznidmmq")) > + (modules '((guix build utils))) > + (snippet '(delete-file-recursively "third-party")))) > + (build-system scons-build-system) > + (arguments > + (list > + #:phases > + #~(modify-phases %standard-phases > + (add-after 'unpack 'disable-other-builds > + (lambda _ > + (substitute* "SConstruct" > + (("for name, tools in builds:") > + "for name, tools in [('opt', [gcc, opt])]:")))) > + (add-after 'unpack 'use-external-unittest-cpp > + (lambda* (#:key inputs #:allow-other-keys) > + (substitute* "SConscript" > + (("unittestpp_env\\.Library") "_dummy = ") > + (("test_env = env.Clone\\(tools=\\[unittestpp, > sajson\\]\\)") > + (string-append > + "test_env = env.Clone(tools=[sajson])\n" > + "test_env.Append(CPPPATH='" > + (search-input-directory inputs > "/include/UnitTest++") Note that you need (or native-inputs inputs) wherever you wrote inputs. > + "', LIBPATH='" > + (string-append #$(this-package-native-input > "unittest-cpp") > + "/lib") > + "', LIBS=['UnitTest++'])"))))) > + (replace 'check > + (lambda* (#:key tests? #:allow-other-keys) > + (when tests? > + (invoke "build/opt/test") > + (invoke "build/opt/test_unsorted")))) > + (replace 'install > + (lambda _ > + (let ((out (string-append #$output "/include"))) > + (install-file "include/sajson.h" out) > + (install-file "include/sajson_ostream.h" > out))))))) For the record, what would a regular install do? > + (native-inputs (list unittest-cpp)) > + (home-page "https://github.com/chadaustin/sajson") > + (synopsis "C++11 header-only, in-place JSON parser") > + (description "@code{sajson} is an in-place JSON parser with > support for > +parsing with only a single memory allocation.") > + (license license:expat)))) > diff --git a/gnu/packages/patches/sajson-build-with-gcc10.patch > b/gnu/packages/patches/sajson-build-with-gcc10.patch > new file mode 100644 > index 0000000000..878706dc79 > --- /dev/null > +++ b/gnu/packages/patches/sajson-build-with-gcc10.patch > @@ -0,0 +1,45 @@ > +This patch is from the upstream pull request > +https://github.com/chadaustin/sajson/pull/54. > +It fixes linking with GCC. > + > +diff --git a/include/sajson.h b/include/sajson.h > +index 8b4e05a..1bd045b 100644 > +--- a/include/sajson.h > ++++ b/include/sajson.h > +@@ -138,12 +138,17 @@ constexpr inline size_t make_element(tag t, > size_t value) { > + // header. This trick courtesy of Rich Geldreich's Purple JSON > parser. > + template <typename unused = void> > + struct globals_struct { > ++ static const unsigned char parse_flags[256]; > ++}; > ++typedef globals_struct<> globals; > ++ > + // clang-format off > + > + // bit 0 (1) - set if: plain ASCII string character > + // bit 1 (2) - set if: whitespace > + // bit 4 (0x10) - set if: 0-9 e E . > +- constexpr static const uint8_t parse_flags[256] = { > ++ template <typename unused> > ++ const unsigned char globals_struct<unused>::parse_flags[256] = > { > + // 0 1 2 3 4 5 6 7 8 9 A > B C D E F > + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, > 0, 0, 2, 0, 0, // 0 > + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, 0, // 1 > +@@ -162,15 +167,13 @@ struct globals_struct { > + }; > + > + // clang-format on > +-}; > +-typedef globals_struct<> globals; > + > +-constexpr inline bool is_plain_string_character(char c) { > ++inline bool is_plain_string_character(char c) { > + // return c >= 0x20 && c <= 0x7f && c != 0x22 && c != 0x5c; > + return (globals::parse_flags[static_cast<unsigned char>(c)] & > 1) != 0; > + } > + > +-constexpr inline bool is_whitespace(char c) { > ++inline bool is_whitespace(char c) { > + // return c == '\r' || c == '\n' || c == '\t' || c == ' '; > + return (globals::parse_flags[static_cast<unsigned char>(c)] & > 2) != 0; > + }
Liliana Marie Prikler <liliana.prikler@gmail.com> writes: > Am Freitag, dem 07.10.2022 um 15:21 +0000 schrieb David Elsing: >> * gnu/packages/cpp.scm (sajson): New variable. >> --- >> gnu/packages/cpp.scm | 60 >> +++++++++++++++++++ >> .../patches/sajson-build-with-gcc10.patch | 45 ++++++++++++++ >> 2 files changed, 105 insertions(+) >> create mode 100644 gnu/packages/patches/sajson-build-with- >> gcc10.patch >> >> diff --git a/gnu/packages/cpp.scm b/gnu/packages/cpp.scm >> index 38a2a9e829..dca0245df5 100644 >> --- a/gnu/packages/cpp.scm >> +++ b/gnu/packages/cpp.scm >> @@ -57,6 +57,7 @@ (define-module (gnu packages cpp) >> #:use-module (guix build-system gnu) >> #:use-module (guix build-system meson) >> #:use-module (guix build-system python) >> + #:use-module (guix build-system scons) >> #:use-module (guix modules) >> #:use-module (guix gexp) >> #:use-module (gnu packages) >> @@ -2005,3 +2006,62 @@ (define-public pocketfft-cpp >> computing Fast Fourier transformations. It supports >> multidimensional arrays, >> different floating point sizes and complex transformations.") >> (license license:bsd-3)))) >> + >> +(define-public sajson >> + (let ((commit "ec644013e34f9984a3cc9ba568cab97a391db9cd") >> + (revision "0")) >> + (package >> + (name "sajson") >> + (version (git-version "1.0" revision commit)) >> + (source (origin >> + (method git-fetch) >> + (uri (git-reference >> + (url "https://github.com/chadaustin/sajson") >> + (commit commit))) >> + (file-name (git-file-name name version)) >> + (patches >> + (search-patches "sajson-build-with-gcc10.patch")) >> + (sha256 >> + (base32 >> + >> "0fjag27w7gvkc5pdhq3ad7yc09rabpzahndw1sgsg04ipznidmmq")) >> + (modules '((guix build utils))) >> + (snippet '(delete-file-recursively "third-party")))) >> + (build-system scons-build-system) >> + (arguments >> + (list >> + #:phases >> + #~(modify-phases %standard-phases >> + (add-after 'unpack 'disable-other-builds >> + (lambda _ >> + (substitute* "SConstruct" >> + (("for name, tools in builds:") >> + "for name, tools in [('opt', [gcc, opt])]:")))) >> + (add-after 'unpack 'use-external-unittest-cpp >> + (lambda* (#:key inputs #:allow-other-keys) >> + (substitute* "SConscript" >> + (("unittestpp_env\\.Library") "_dummy = ") >> + (("test_env = env.Clone\\(tools=\\[unittestpp, >> sajson\\]\\)") >> + (string-append >> + "test_env = env.Clone(tools=[sajson])\n" >> + "test_env.Append(CPPPATH='" >> + (search-input-directory inputs >> "/include/UnitTest++") > Note that you need (or native-inputs inputs) wherever you wrote inputs. Is %build-inputs ok? >> + "', LIBPATH='" >> + (string-append #$(this-package-native-input >> "unittest-cpp") >> + "/lib") >> + "', LIBS=['UnitTest++'])"))))) >> + (replace 'check >> + (lambda* (#:key tests? #:allow-other-keys) >> + (when tests? >> + (invoke "build/opt/test") >> + (invoke "build/opt/test_unsorted")))) >> + (replace 'install >> + (lambda _ >> + (let ((out (string-append #$output "/include"))) >> + (install-file "include/sajson.h" out) >> + (install-file "include/sajson_ostream.h" >> out))))))) > For the record, what would a regular install do? Just nothing. >> + (native-inputs (list unittest-cpp)) >> + (home-page "https://github.com/chadaustin/sajson") >> + (synopsis "C++11 header-only, in-place JSON parser") >> + (description "@code{sajson} is an in-place JSON parser with >> support for >> +parsing with only a single memory allocation.") >> + (license license:expat)))) >> diff --git a/gnu/packages/patches/sajson-build-with-gcc10.patch >> b/gnu/packages/patches/sajson-build-with-gcc10.patch >> new file mode 100644 >> index 0000000000..878706dc79 >> --- /dev/null >> +++ b/gnu/packages/patches/sajson-build-with-gcc10.patch >> @@ -0,0 +1,45 @@ >> +This patch is from the upstream pull request >> +https://github.com/chadaustin/sajson/pull/54. >> +It fixes linking with GCC. >> + >> +diff --git a/include/sajson.h b/include/sajson.h >> +index 8b4e05a..1bd045b 100644 >> +--- a/include/sajson.h >> ++++ b/include/sajson.h >> +@@ -138,12 +138,17 @@ constexpr inline size_t make_element(tag t, >> size_t value) { >> + // header. This trick courtesy of Rich Geldreich's Purple JSON >> parser. >> + template <typename unused = void> >> + struct globals_struct { >> ++ static const unsigned char parse_flags[256]; >> ++}; >> ++typedef globals_struct<> globals; >> ++ >> + // clang-format off >> + >> + // bit 0 (1) - set if: plain ASCII string character >> + // bit 1 (2) - set if: whitespace >> + // bit 4 (0x10) - set if: 0-9 e E . >> +- constexpr static const uint8_t parse_flags[256] = { >> ++ template <typename unused> >> ++ const unsigned char globals_struct<unused>::parse_flags[256] = >> { >> + // 0 1 2 3 4 5 6 7 8 9 A >> B C D E F >> + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, >> 0, 0, 2, 0, 0, // 0 >> + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >> 0, 0, 0, 0, 0, // 1 >> +@@ -162,15 +167,13 @@ struct globals_struct { >> + }; >> + >> + // clang-format on >> +-}; >> +-typedef globals_struct<> globals; >> + >> +-constexpr inline bool is_plain_string_character(char c) { >> ++inline bool is_plain_string_character(char c) { >> + // return c >= 0x20 && c <= 0x7f && c != 0x22 && c != 0x5c; >> + return (globals::parse_flags[static_cast<unsigned char>(c)] & >> 1) != 0; >> + } >> + >> +-constexpr inline bool is_whitespace(char c) { >> ++inline bool is_whitespace(char c) { >> + // return c == '\r' || c == '\n' || c == '\t' || c == ' '; >> + return (globals::parse_flags[static_cast<unsigned char>(c)] & >> 2) != 0; >> + }
Am Donnerstag, dem 13.10.2022 um 20:59 +0000 schrieb David Elsing: > Liliana Marie Prikler <liliana.prikler@gmail.com> writes: > > > Am Freitag, dem 07.10.2022 um 15:21 +0000 schrieb David Elsing: > > > * gnu/packages/cpp.scm (sajson): New variable. > > > --- > > > gnu/packages/cpp.scm | 60 > > > +++++++++++++++++++ > > > .../patches/sajson-build-with-gcc10.patch | 45 > > > ++++++++++++++ > > > 2 files changed, 105 insertions(+) > > > create mode 100644 gnu/packages/patches/sajson-build-with- > > > gcc10.patch > > > > > > diff --git a/gnu/packages/cpp.scm b/gnu/packages/cpp.scm > > > index 38a2a9e829..dca0245df5 100644 > > > --- a/gnu/packages/cpp.scm > > > +++ b/gnu/packages/cpp.scm > > > @@ -57,6 +57,7 @@ (define-module (gnu packages cpp) > > > #:use-module (guix build-system gnu) > > > #:use-module (guix build-system meson) > > > #:use-module (guix build-system python) > > > + #:use-module (guix build-system scons) > > > #:use-module (guix modules) > > > #:use-module (guix gexp) > > > #:use-module (gnu packages) > > > @@ -2005,3 +2006,62 @@ (define-public pocketfft-cpp > > > computing Fast Fourier transformations. It supports > > > multidimensional arrays, > > > different floating point sizes and complex transformations.") > > > (license license:bsd-3)))) > > > + > > > +(define-public sajson > > > + (let ((commit "ec644013e34f9984a3cc9ba568cab97a391db9cd") > > > + (revision "0")) > > > + (package > > > + (name "sajson") > > > + (version (git-version "1.0" revision commit)) > > > + (source (origin > > > + (method git-fetch) > > > + (uri (git-reference > > > + (url > > > "https://github.com/chadaustin/sajson") > > > + (commit commit))) > > > + (file-name (git-file-name name version)) > > > + (patches > > > + (search-patches "sajson-build-with- > > > gcc10.patch")) > > > + (sha256 > > > + (base32 > > > + > > > "0fjag27w7gvkc5pdhq3ad7yc09rabpzahndw1sgsg04ipznidmmq")) > > > + (modules '((guix build utils))) > > > + (snippet '(delete-file-recursively "third- > > > party")))) > > > + (build-system scons-build-system) > > > + (arguments > > > + (list > > > + #:phases > > > + #~(modify-phases %standard-phases > > > + (add-after 'unpack 'disable-other-builds > > > + (lambda _ > > > + (substitute* "SConstruct" > > > + (("for name, tools in builds:") > > > + "for name, tools in [('opt', [gcc, > > > opt])]:")))) > > > + (add-after 'unpack 'use-external-unittest-cpp > > > + (lambda* (#:key inputs #:allow-other-keys) > > > + (substitute* "SConscript" > > > + (("unittestpp_env\\.Library") "_dummy = ") > > > + (("test_env = env.Clone\\(tools=\\[unittestpp, > > > sajson\\]\\)") > > > + (string-append > > > + "test_env = env.Clone(tools=[sajson])\n" > > > + "test_env.Append(CPPPATH='" > > > + (search-input-directory inputs > > > "/include/UnitTest++") > > Note that you need (or native-inputs inputs) wherever you wrote > > inputs. > Is %build-inputs ok? No, we only use this in trivial-build-system and other places where we don't have the split. > > > + "', LIBPATH='" > > > + (string-append #$(this-package-native-input > > > "unittest-cpp") > > > + "/lib") > > > + "', LIBS=['UnitTest++'])"))))) > > > + (replace 'check > > > + (lambda* (#:key tests? #:allow-other-keys) > > > + (when tests? > > > + (invoke "build/opt/test") > > > + (invoke "build/opt/test_unsorted")))) > > > + (replace 'install > > > + (lambda _ > > > + (let ((out (string-append #$output "/include"))) > > > + (install-file "include/sajson.h" out) > > > + (install-file "include/sajson_ostream.h" > > > out))))))) > > For the record, what would a regular install do? > Just nothing. Fair enough. > > > + (native-inputs (list unittest-cpp)) > > > + (home-page "https://github.com/chadaustin/sajson") > > > + (synopsis "C++11 header-only, in-place JSON parser") > > > + (description "@code{sajson} is an in-place JSON parser > > > with > > > support for > > > +parsing with only a single memory allocation.") > > > + (license license:expat)))) > > > diff --git a/gnu/packages/patches/sajson-build-with-gcc10.patch > > > b/gnu/packages/patches/sajson-build-with-gcc10.patch > > > new file mode 100644 > > > index 0000000000..878706dc79 > > > --- /dev/null > > > +++ b/gnu/packages/patches/sajson-build-with-gcc10.patch > > > @@ -0,0 +1,45 @@ > > > +This patch is from the upstream pull request > > > +https://github.com/chadaustin/sajson/pull/54. > > > +It fixes linking with GCC. > > > + > > > +diff --git a/include/sajson.h b/include/sajson.h > > > +index 8b4e05a..1bd045b 100644 > > > +--- a/include/sajson.h > > > ++++ b/include/sajson.h > > > +@@ -138,12 +138,17 @@ constexpr inline size_t make_element(tag > > > t, > > > size_t value) { > > > + // header. This trick courtesy of Rich Geldreich's Purple JSON > > > parser. > > > + template <typename unused = void> > > > + struct globals_struct { > > > ++ static const unsigned char parse_flags[256]; > > > ++}; > > > ++typedef globals_struct<> globals; > > > ++ > > > + // clang-format off > > > + > > > + // bit 0 (1) - set if: plain ASCII string character > > > + // bit 1 (2) - set if: whitespace > > > + // bit 4 (0x10) - set if: 0-9 e E . > > > +- constexpr static const uint8_t parse_flags[256] = { > > > ++ template <typename unused> > > > ++ const unsigned char > > > globals_struct<unused>::parse_flags[256] = > > > { > > > + // 0 1 2 3 4 5 6 7 8 9 > > > A > > > B C D E F > > > + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, > > > 2, > > > 0, 0, 2, 0, 0, // 0 > > > + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, > > > 0, > > > 0, 0, 0, 0, 0, // 1 > > > +@@ -162,15 +167,13 @@ struct globals_struct { > > > + }; > > > + > > > + // clang-format on > > > +-}; > > > +-typedef globals_struct<> globals; > > > + > > > +-constexpr inline bool is_plain_string_character(char c) { > > > ++inline bool is_plain_string_character(char c) { > > > + // return c >= 0x20 && c <= 0x7f && c != 0x22 && c != 0x5c; > > > + return (globals::parse_flags[static_cast<unsigned char>(c)] > > > & > > > 1) != 0; > > > + } > > > + > > > +-constexpr inline bool is_whitespace(char c) { > > > ++inline bool is_whitespace(char c) { > > > + // return c == '\r' || c == '\n' || c == '\t' || c == ' '; > > > + return (globals::parse_flags[static_cast<unsigned char>(c)] > > > & > > > 2) != 0; > > > + }
diff --git a/gnu/packages/cpp.scm b/gnu/packages/cpp.scm index 38a2a9e829..dca0245df5 100644 --- a/gnu/packages/cpp.scm +++ b/gnu/packages/cpp.scm @@ -57,6 +57,7 @@ (define-module (gnu packages cpp) #:use-module (guix build-system gnu) #:use-module (guix build-system meson) #:use-module (guix build-system python) + #:use-module (guix build-system scons) #:use-module (guix modules) #:use-module (guix gexp) #:use-module (gnu packages) @@ -2005,3 +2006,62 @@ (define-public pocketfft-cpp computing Fast Fourier transformations. It supports multidimensional arrays, different floating point sizes and complex transformations.") (license license:bsd-3)))) + +(define-public sajson + (let ((commit "ec644013e34f9984a3cc9ba568cab97a391db9cd") + (revision "0")) + (package + (name "sajson") + (version (git-version "1.0" revision commit)) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/chadaustin/sajson") + (commit commit))) + (file-name (git-file-name name version)) + (patches + (search-patches "sajson-build-with-gcc10.patch")) + (sha256 + (base32 + "0fjag27w7gvkc5pdhq3ad7yc09rabpzahndw1sgsg04ipznidmmq")) + (modules '((guix build utils))) + (snippet '(delete-file-recursively "third-party")))) + (build-system scons-build-system) + (arguments + (list + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'disable-other-builds + (lambda _ + (substitute* "SConstruct" + (("for name, tools in builds:") + "for name, tools in [('opt', [gcc, opt])]:")))) + (add-after 'unpack 'use-external-unittest-cpp + (lambda* (#:key inputs #:allow-other-keys) + (substitute* "SConscript" + (("unittestpp_env\\.Library") "_dummy = ") + (("test_env = env.Clone\\(tools=\\[unittestpp, sajson\\]\\)") + (string-append + "test_env = env.Clone(tools=[sajson])\n" + "test_env.Append(CPPPATH='" + (search-input-directory inputs "/include/UnitTest++") + "', LIBPATH='" + (string-append #$(this-package-native-input "unittest-cpp") + "/lib") + "', LIBS=['UnitTest++'])"))))) + (replace 'check + (lambda* (#:key tests? #:allow-other-keys) + (when tests? + (invoke "build/opt/test") + (invoke "build/opt/test_unsorted")))) + (replace 'install + (lambda _ + (let ((out (string-append #$output "/include"))) + (install-file "include/sajson.h" out) + (install-file "include/sajson_ostream.h" out))))))) + (native-inputs (list unittest-cpp)) + (home-page "https://github.com/chadaustin/sajson") + (synopsis "C++11 header-only, in-place JSON parser") + (description "@code{sajson} is an in-place JSON parser with support for +parsing with only a single memory allocation.") + (license license:expat)))) diff --git a/gnu/packages/patches/sajson-build-with-gcc10.patch b/gnu/packages/patches/sajson-build-with-gcc10.patch new file mode 100644 index 0000000000..878706dc79 --- /dev/null +++ b/gnu/packages/patches/sajson-build-with-gcc10.patch @@ -0,0 +1,45 @@ +This patch is from the upstream pull request +https://github.com/chadaustin/sajson/pull/54. +It fixes linking with GCC. + +diff --git a/include/sajson.h b/include/sajson.h +index 8b4e05a..1bd045b 100644 +--- a/include/sajson.h ++++ b/include/sajson.h +@@ -138,12 +138,17 @@ constexpr inline size_t make_element(tag t, size_t value) { + // header. This trick courtesy of Rich Geldreich's Purple JSON parser. + template <typename unused = void> + struct globals_struct { ++ static const unsigned char parse_flags[256]; ++}; ++typedef globals_struct<> globals; ++ + // clang-format off + + // bit 0 (1) - set if: plain ASCII string character + // bit 1 (2) - set if: whitespace + // bit 4 (0x10) - set if: 0-9 e E . +- constexpr static const uint8_t parse_flags[256] = { ++ template <typename unused> ++ const unsigned char globals_struct<unused>::parse_flags[256] = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 +@@ -162,15 +167,13 @@ struct globals_struct { + }; + + // clang-format on +-}; +-typedef globals_struct<> globals; + +-constexpr inline bool is_plain_string_character(char c) { ++inline bool is_plain_string_character(char c) { + // return c >= 0x20 && c <= 0x7f && c != 0x22 && c != 0x5c; + return (globals::parse_flags[static_cast<unsigned char>(c)] & 1) != 0; + } + +-constexpr inline bool is_whitespace(char c) { ++inline bool is_whitespace(char c) { + // return c == '\r' || c == '\n' || c == '\t' || c == ' '; + return (globals::parse_flags[static_cast<unsigned char>(c)] & 2) != 0; + }