From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 9024315808A for ; Sun, 13 Jul 2025 13:01:31 +0000 (UTC) Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: relay-lists.gentoo.org@gentoo.org) by smtp.gentoo.org (Postfix) with ESMTPSA id 773B6341EE0 for ; Sun, 13 Jul 2025 13:01:31 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id 451EE11036B; Sun, 13 Jul 2025 13:01:30 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bobolink.gentoo.org (Postfix) with ESMTPS id 3970511036B for ; Sun, 13 Jul 2025 13:01:29 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 7B224341CC6 for ; Sun, 13 Jul 2025 13:01:29 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id CD76F1851 for ; Sun, 13 Jul 2025 13:01:27 +0000 (UTC) From: "Jan-Espen Oversand" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Jan-Espen Oversand" Message-ID: <1752411490.9e5085234797d529eca828d179334b8045382e9f.sigsegv@gentoo> Subject: [gentoo-commits] repo/proj/guru:dev commit in: dev-cpp/cpprestsdk/, dev-cpp/cpprestsdk/files/ X-VCS-Repository: repo/proj/guru X-VCS-Files: dev-cpp/cpprestsdk/cpprestsdk-2.10.19-r6.ebuild dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-char-traits-patch.patch dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-json-unique-ptr.patch X-VCS-Directories: dev-cpp/cpprestsdk/ dev-cpp/cpprestsdk/files/ X-VCS-Committer: sigsegv X-VCS-Committer-Name: Jan-Espen Oversand X-VCS-Revision: 9e5085234797d529eca828d179334b8045382e9f X-VCS-Branch: dev Date: Sun, 13 Jul 2025 13:01:27 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: d1eb8b98-735f-48b0-b686-25ce4fb767dc X-Archives-Hash: fd8b2fbfaff0ef89dcd70c493950ee80 commit: 9e5085234797d529eca828d179334b8045382e9f Author: Jan-Espen Oversand radiotube org> AuthorDate: Sun Jul 13 12:58:10 2025 +0000 Commit: Jan-Espen Oversand radiotube org> CommitDate: Sun Jul 13 12:58:10 2025 +0000 URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=9e508523 dev-cpp/cpprestsdk: patch for llvm up to 20 Llvm has previously required sizes/implementation of objects used in containers and std::unique_ptr for more methods than gcc. Also in later llvms like 19 and 20 unsigned types are not possible to use with the std::char_traits. Cpprestsdk does use a lot of unsigned types with C++ streams and while that seems to be fine with MSVC and at least gcc up until some point, it does not work at all with llvm 19 and 20. Signed-off-by: Jan-Espen Oversand radiotube.org> dev-cpp/cpprestsdk/cpprestsdk-2.10.19-r6.ebuild | 41 ++ ...cpprestsdk-2.10.19-llvm-char-traits-patch.patch | 429 +++++++++++++++++++++ .../cpprestsdk-2.10.19-llvm-json-unique-ptr.patch | 216 +++++++++++ 3 files changed, 686 insertions(+) diff --git a/dev-cpp/cpprestsdk/cpprestsdk-2.10.19-r6.ebuild b/dev-cpp/cpprestsdk/cpprestsdk-2.10.19-r6.ebuild new file mode 100644 index 0000000000..f8d72b6554 --- /dev/null +++ b/dev-cpp/cpprestsdk/cpprestsdk-2.10.19-r6.ebuild @@ -0,0 +1,41 @@ +# Copyright 1999-2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit cmake + +DESCRIPTION="A Microsoft project for cloud-based client-server communication." +HOMEPAGE="https://github.com/microsoft/cpprestsdk" +SRC_URI="https://github.com/microsoft/cpprestsdk/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz" +LICENSE="MIT" +SLOT="0" +KEYWORDS="~amd64 ~x86" + +RDEPEND=">=dev-libs/openssl-1.1.1q + >=dev-libs/boost-1.80.0-r1:= + >=sys-libs/zlib-1.2.13-r1" + +DEPEND="${RDEPEND}" + +BDEPEND=" + app-alternatives/ninja + >=sys-devel/gcc-11.3.0 + >=virtual/pkgconfig-2-r1 + >=dev-cpp/websocketpp-0.8.2 +" + +PATCHES=( + "${FILESDIR}"/cpprestsdk-${PV}-warnings.patch + "${FILESDIR}"/cpprestsdk-${PV}-disabl-int-tests.patch + "${FILESDIR}"/cpprestsdk-${PV}-disable-werror-default.patch + "${FILESDIR}"/cpprestsdk-${PV}-boost-1.87-compat.patch + "${FILESDIR}"/cpprestsdk-${PV}-cmake-4.patch + "${FILESDIR}"/cpprestsdk-${PV}-llvm-char-traits-patch.patch + "${FILESDIR}"/cpprestsdk-${PV}-llvm-json-unique-ptr.patch +) + +src_configure() { + local mycmakeargs=( -DCMAKE_BUILD_TYPE=Release ) + cmake_src_configure +} diff --git a/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-char-traits-patch.patch b/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-char-traits-patch.patch new file mode 100644 index 0000000000..4d123d76f7 --- /dev/null +++ b/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-char-traits-patch.patch @@ -0,0 +1,429 @@ +--- a/Release/include/cpprest/streams.h (revision 0b1ce318a757bbfb89bdb0fffb61ca4e38dc3b33) ++++ b/Release/include/cpprest/streams.h (revision 32b322b564e5e540ff02393ffe3bd3bade8d299c) +@@ -16,6 +16,7 @@ + #define CASA_STREAMS_H + + #include "cpprest/astreambuf.h" ++#include "cpprest/details/char_traits.h" + #include + #include + +@@ -60,30 +61,95 @@ + concurrency::streams::streambuf m_buffer; + }; + +-template ++template::TraitsType> + struct Value2StringFormatter + { ++ struct SanitizeInput ++ { ++ const std::basic_string &operator () (const std::basic_string &input) ++ { ++ return input; ++ } ++ template std::basic_string operator () (const std::basic_string &input) ++ { ++ return {reinterpret_cast(input.c_str()), input.size()}; ++ } ++ const char *operator () (const char *input) { ++ return input; ++ } ++ const char *operator () (const unsigned char *input) ++ { ++ return reinterpret_cast(input); ++ } ++ template T operator () (T input) ++ { ++ return input; ++ } ++ }; ++ struct GenerateFormatOutput ++ { ++ std::basic_string &&operator() (std::basic_string &&result) ++ { ++ return std::move(result); ++ } ++ std::basic_string operator() (const std::basic_string &intermediate) ++ { ++ return {reinterpret_cast(intermediate.c_str()), intermediate.size()}; ++ } ++ }; + template +- static std::basic_string format(const T& val) ++ static std::basic_string format(const T& val) + { +- std::basic_ostringstream ss; ++ typename std::conditional< ++ sizeof(CharType) == 1, ++ std::basic_ostringstream, ++ std::basic_ostringstream::type> ++ >::type ss; ++ SanitizeInput sanitizer; ++ ss << sanitizer(val); ++ typename std::conditional< ++ sizeof(CharType) == 1, ++ std::basic_string, ++ std::basic_string::type> ++ >::type str = ss.str(); ++ GenerateFormatOutput generateFormatOutput; ++ return generateFormatOutput(std::move(str)); ++ } ++}; ++ ++template ++struct Value2StringFormatterUint8Format ++{ ++ std::basic_string operator () (const T& val) ++ { ++ std::basic_ostringstream ss; + ss << val; +- return ss.str(); ++ return reinterpret_cast(ss.str().c_str()); ++ } ++}; ++ ++template ++struct Value2StringFormatterUint8Format> ++{ ++ std::basic_string operator () ( ++ const std::basic_string::TraitsType>& val) ++ { ++ Value2StringFormatterUint8Format> format; ++ return format(reinterpret_cast&>(val)); + } + }; + + template<> + struct Value2StringFormatter + { +- template +- static std::basic_string format(const T& val) ++ template ::TraitsType> ++ static std::basic_string format(const T& val) + { +- std::basic_ostringstream ss; +- ss << val; +- return reinterpret_cast(ss.str().c_str()); ++ Value2StringFormatterUint8Format format; ++ return format(val); + } + +- static std::basic_string format(const utf16string& val) ++ static std::basic_string::TraitsType> format(const utf16string& val) + { + return format(utility::conversions::utf16_to_utf8(val)); + } +@@ -262,7 +328,7 @@ + /// Write the specified string to the output stream. + /// + /// Input string. +- pplx::task print(const std::basic_string& str) const ++ pplx::task print(const std::basic_string& str) const + { + pplx::task result; + if (!_verify_and_return_task(details::_out_stream_msg, result)) return result; +@@ -273,7 +339,7 @@ + } + else + { +- auto sharedStr = std::make_shared>(str); ++ auto sharedStr = std::make_shared>(str); + return helper()->m_buffer.putn_nocopy(sharedStr->c_str(), sharedStr->size()).then([sharedStr](size_t size) { + return size; + }); +@@ -294,7 +360,7 @@ + if (!_verify_and_return_task(details::_out_stream_msg, result)) return result; + // TODO in the future this could be improved to have Value2StringFormatter avoid another unnecessary copy + // by putting the string on the heap before calling the print string overload. +- return print(details::Value2StringFormatter::format(val)); ++ return print(details::Value2StringFormatter::format(val)); + } + + /// +--- a/Release/include/cpprest/astreambuf.h (revision d17f091b5a753b33fb455e92b590fc9f4e921119) ++++ b/Release/include/cpprest/astreambuf.h (revision 4188ad89b2cf2e8de3cc3513adcf400fbfdc5ce7) +@@ -15,6 +15,7 @@ + + #include "cpprest/asyncrt_utils.h" + #include "cpprest/details/basic_types.h" ++#include "cpprest/details/char_traits.h" + #include "pplx/pplxtasks.h" + #include + #include +@@ -56,55 +57,28 @@ + /// + /// The data type of the basic element of the stream. + /// ++namespace detail ++{ + template +-struct char_traits : std::char_traits<_CharType> ++struct char_traits : utility::CanUseStdCharTraits<_CharType>::TraitsType + { + /// + /// Some synchronous functions will return this value if the operation + /// requires an asynchronous call in a given situation. + /// + /// An int_type value which implies that an asynchronous call is required. +- static typename std::char_traits<_CharType>::int_type requires_async() ++ static typename utility::CanUseStdCharTraits<_CharType>::TraitsType::int_type requires_async() + { +- return std::char_traits<_CharType>::eof() - 1; ++ return utility::CanUseStdCharTraits<_CharType>::TraitsType::eof() - 1; + } ++}; ++} ++template struct char_traits : detail::char_traits<_CharType> { + }; + #if !defined(_WIN32) +-template<> +-struct char_traits : private std::char_traits +-{ +-public: +- typedef unsigned char char_type; +- +- using std::char_traits::eof; +- using std::char_traits::int_type; +- using std::char_traits::off_type; +- using std::char_traits::pos_type; +- +- static size_t length(const unsigned char* str) +- { +- return std::char_traits::length(reinterpret_cast(str)); +- } +- +- static void assign(unsigned char& left, const unsigned char& right) { left = right; } +- static unsigned char* assign(unsigned char* left, size_t n, unsigned char value) +- { +- return reinterpret_cast( +- std::char_traits::assign(reinterpret_cast(left), n, static_cast(value))); +- } +- +- static unsigned char* copy(unsigned char* left, const unsigned char* right, size_t n) +- { +- return reinterpret_cast( +- std::char_traits::copy(reinterpret_cast(left), reinterpret_cast(right), n)); +- } +- +- static unsigned char* move(unsigned char* left, const unsigned char* right, size_t n) +- { +- return reinterpret_cast( +- std::char_traits::move(reinterpret_cast(left), reinterpret_cast(right), n)); +- } +- ++template <> struct char_traits : detail::char_traits { ++ typedef typename std::char_traits::int_type int_type; ++ static int_type eof() { return std::char_traits::eof(); } + static int_type requires_async() { return eof() - 1; } + }; + #endif +new file mode 100644 +--- /dev/null (revision 4188ad89b2cf2e8de3cc3513adcf400fbfdc5ce7) ++++ b/Release/include/cpprest/details/char_traits.h (revision 4188ad89b2cf2e8de3cc3513adcf400fbfdc5ce7) +@@ -0,0 +1,102 @@ ++// ++// Created by sigsegv on 6/28/25. ++// ++ ++#ifndef CPPRESTSDK_ROOT_CHAR_TRAITS_H ++#define CPPRESTSDK_ROOT_CHAR_TRAITS_H ++ ++#include ++#include ++ ++namespace utility { ++ ++namespace detail { ++ ++template struct IntTypeFor { ++ typedef typename std::conditional::value, unsigned long long int, long long int>::type type; ++}; ++template <> struct IntTypeFor { ++ typedef typename std::char_traits::int_type type; ++}; ++template <> struct IntTypeFor { ++ typedef typename std::make_unsigned::int_type>::type type; ++}; ++ ++template class DetailCharTraits ++{ ++public: ++ using char_type = T; ++ using int_type = typename IntTypeFor::type; ++ using off_type = std::streamoff; ++ using pos_type = std::streampos; ++ using state_type = mbstate_t; ++ ++ static void assign(char_type& r, const char_type& a) noexcept { r = a; } ++ static char_type to_char_type(int_type c) noexcept { return char_type(c); } ++ static int_type to_int_type(char_type c) noexcept { return c; } ++ static bool eq(char_type a, char_type b) noexcept { return a == b; } ++ static bool lt(char_type a, char_type b) noexcept { return a < b; } ++ static int compare(const char_type* s1,const char_type* s2,size_t n){ ++ for (; n--; ++s1, ++s2) { ++ if (!eq(*s1, *s2)) ++ return lt(*s1,*s2)?-1:1; ++ } ++ return 0; ++ } ++ static size_t length(const char_type* s){ ++ const char_type* p = s; ++ while (*p) ++ ++p; ++ return size_t(p - s); ++ } ++ static const char_type* find(const char_type* s,size_t n,const char_type& a){ ++ for (; n--; ++s) ++ { ++ if (eq(*s, a)) ++ return s; ++ return nullptr; ++ } ++ } ++ static char_type* move (char_type* r,const char_type* s,size_t n){ ++ return (char_type*)memmove(r, s, n * sizeof(char_type)); ++ } ++ static char_type* copy (char_type* r,const char_type* s,size_t n){ ++ return (char_type*)memcpy (r, s, n * sizeof(char_type)); ++ } ++ static char_type* assign(char_type* r,size_t n,char_type a){ ++ if (sizeof(char_type) == 1) ++ { ++ return (char_type*)memset(r, a, n); ++ } ++ else ++ { ++ for (char_type *s = r; n--; ++s) ++ { ++ *s = a; ++ } ++ } ++ } ++ static int_type eof() noexcept { return ~0u; } ++ static int_type not_eof(int_type c) noexcept { return c == eof() ? 0 : c; } ++}; ++ ++template struct CanUseStdCharTraits : public std::false_type ++{ ++public: ++ typedef DetailCharTraits TraitsType; ++}; ++ ++template struct CanUseStdCharTraits::eq(std::declval(), std::declval()))> : public std::true_type ++{ ++public: ++ typedef std::char_traits TraitsType; ++}; ++ ++} ++ ++template struct CanUseStdCharTraits : detail::CanUseStdCharTraits::type>::type> { ++}; ++ ++} ++ ++#endif // CPPRESTSDK_ROOT_CHAR_TRAITS_H +--- a/Release/tests/functional/streams/memstream_tests.cpp (revision d17f091b5a753b33fb455e92b590fc9f4e921119) ++++ b/Release/tests/functional/streams/memstream_tests.cpp (revision 6df13a8c0417ef700c0f164bcd0686ad46f66fd9) +@@ -8,6 +8,7 @@ + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ ++#include "cpprest/details/char_traits.h" + #include "stdafx.h" + #if defined(__cplusplus_winrt) + #include +@@ -32,7 +33,7 @@ + { + VERIFY_IS_TRUE(wbuf.can_write()); + +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((typename StreamBufferType::char_type)0); + s.push_back((typename StreamBufferType::char_type)1); + s.push_back((typename StreamBufferType::char_type)2); +@@ -137,7 +138,7 @@ + { + VERIFY_IS_TRUE(wbuf.can_write()); + +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((typename StreamBufferType::char_type)0); + s.push_back((typename StreamBufferType::char_type)1); + s.push_back((typename StreamBufferType::char_type)2); +@@ -169,7 +170,7 @@ + + typedef concurrency::streams::rawptr_buffer StreamBufferType; + +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((CharType)0); + s.push_back((CharType)1); + s.push_back((CharType)2); +@@ -198,7 +199,7 @@ + typedef concurrency::streams::container_buffer StreamBufferType; + typedef typename concurrency::streams::container_buffer::char_type CharType; + +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((CharType)0); + s.push_back((CharType)1); + s.push_back((CharType)2); +@@ -553,7 +554,7 @@ + VERIFY_IS_TRUE(rwbuf.can_read()); + VERIFY_IS_TRUE(rwbuf.can_write()); + VERIFY_IS_FALSE(rwbuf.is_eof()); +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((typename StreamBufferType::char_type)0); + s.push_back((typename StreamBufferType::char_type)1); + s.push_back((typename StreamBufferType::char_type)2); +@@ -684,7 +685,7 @@ + VERIFY_IS_TRUE(rwbuf.can_write()); + + // Write 4 characters +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((typename StreamBufferType::char_type)0); + s.push_back((typename StreamBufferType::char_type)1); + s.push_back((typename StreamBufferType::char_type)2); +@@ -726,7 +727,7 @@ + VERIFY_IS_TRUE(rwbuf.can_write()); + + // Write 4 characters +- std::basic_string s; ++ std::basic_string::TraitsType> s; + s.push_back((typename StreamBufferType::char_type)0); + s.push_back((typename StreamBufferType::char_type)1); + s.push_back((typename StreamBufferType::char_type)2); +--- a/Release/tests/functional/streams/stdstream_tests.cpp (revision d17f091b5a753b33fb455e92b590fc9f4e921119) ++++ b/Release/tests/functional/streams/stdstream_tests.cpp (revision 6df13a8c0417ef700c0f164bcd0686ad46f66fd9) +@@ -13,6 +13,7 @@ + #include "cpprest/filestream.h" + #include "cpprest/producerconsumerstream.h" + #include "cpprest/rawptrstream.h" ++#include "cpprest/details/char_traits.h" + + #if (!defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS)) && !defined(__cplusplus_winrt) + #include +@@ -303,7 +304,8 @@ + + const std::streamsize iterations = 100; + +- const std::string the_alphabet("abcdefghijklmnopqrstuvwxyz"); ++ const char *the_alphabet_characters = "abcdefghijklmnopqrstuvwxyz"; ++ const std::basic_string::TraitsType> the_alphabet(reinterpret_cast(the_alphabet_characters)); + + auto writer = pplx::create_task([ostream, iterations, the_alphabet]() { + auto os = ostream; +@@ -341,7 +343,8 @@ + + const std::streamsize iterations = 100; + +- const std::string the_alphabet("abcdefghijklmnopqrstuvwxyz"); ++ const char *the_alphabet_chars = "abcdefghijklmnopqrstuvwxyz"; ++ const std::basic_string::TraitsType> the_alphabet(reinterpret_cast(the_alphabet_chars)); + + auto writer = pplx::create_task([ostream, iterations, the_alphabet]() { + auto os = ostream; diff --git a/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-json-unique-ptr.patch b/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-json-unique-ptr.patch new file mode 100644 index 0000000000..f609f52a1d --- /dev/null +++ b/dev-cpp/cpprestsdk/files/cpprestsdk-2.10.19-llvm-json-unique-ptr.patch @@ -0,0 +1,216 @@ +--- a/Release/include/cpprest/json.h ++++ b/Release/include/cpprest/json.h +@@ -737,12 +737,10 @@ + _ASYNCRTIMP void format(std::basic_string& string) const; + + #ifdef ENABLE_JSON_VALUE_VISUALIZER +- explicit value(std::unique_ptr v, value_type kind) : m_value(std::move(v)), m_kind(kind) ++ explicit value(std::unique_ptr v, value_type kind); + #else +- explicit value(std::unique_ptr v) : m_value(std::move(v)) ++ explicit value(std::unique_ptr v); + #endif +- { +- } + + std::unique_ptr m_value; + #ifdef ENABLE_JSON_VALUE_VISUALIZER +@@ -831,9 +829,9 @@ + typedef storage_type::size_type size_type; + + private: +- array() : m_elements() {} +- array(size_type size) : m_elements(size) {} +- array(storage_type elements) : m_elements(std::move(elements)) {} ++ array(); ++ array(size_type size); ++ array(storage_type elements); + + public: + /// +@@ -915,20 +913,13 @@ + /// Iterator to the new location of the element following the erased element. + /// GCC doesn't support erase with const_iterator on vector yet. In the future this should be + /// changed. +- iterator erase(iterator position) { return m_elements.erase(position); } ++ iterator erase(iterator position); + + /// + /// Deletes the element at an index of the JSON array. + /// + /// The index of the element to delete. +- void erase(size_type index) +- { +- if (index >= m_elements.size()) +- { +- throw json_exception("index out of bounds"); +- } +- m_elements.erase(m_elements.begin() + index); +- } ++ void erase(size_type index); + + /// + /// Accesses an element of a JSON array. Throws when index out of bounds. +@@ -959,15 +950,7 @@ + /// + /// The index of an element in the JSON array. + /// A reference to the value kept in the field. +- json::value& operator[](size_type index) +- { +- msl::safeint3::SafeInt nMinSize(index); +- nMinSize += 1; +- msl::safeint3::SafeInt nlastSize(m_elements.size()); +- if (nlastSize < nMinSize) m_elements.resize((size_type)nMinSize); +- +- return m_elements[index]; +- } ++ json::value& operator[](size_type index); + + /// + /// Gets the number of elements of the array. +@@ -998,14 +981,8 @@ + typedef storage_type::size_type size_type; + + private: +- object(bool keep_order = false) : m_elements(), m_keep_order(keep_order) {} +- object(storage_type elements, bool keep_order = false) : m_elements(std::move(elements)), m_keep_order(keep_order) +- { +- if (!keep_order) +- { +- sort(m_elements.begin(), m_elements.end(), compare_pairs); +- } +- } ++ object(bool keep_order = false); ++ object(storage_type elements, bool keep_order = false); + + public: + /// +@@ -1087,22 +1064,13 @@ + /// Iterator to the new location of the element following the erased element. + /// GCC doesn't support erase with const_iterator on vector yet. In the future this should be + /// changed. +- iterator erase(iterator position) { return m_elements.erase(position); } ++ iterator erase(iterator position); + + /// + /// Deletes an element of the JSON object. If the key doesn't exist, this method throws. + /// + /// The key of an element in the JSON object. +- void erase(const utility::string_t& key) +- { +- auto iter = find_by_key(key); +- if (iter == m_elements.end()) +- { +- throw web::json::json_exception("Key not found"); +- } +- +- m_elements.erase(iter); +- } ++ void erase(const utility::string_t& key); + + /// + /// Accesses an element of a JSON object. If the key doesn't exist, this method throws. +@@ -1142,17 +1110,7 @@ + /// The key of an element in the JSON object. + /// If the key exists, a reference to the value kept in the field, otherwise a newly created null value + /// that will be stored for the given key. +- json::value& operator[](const utility::string_t& key) +- { +- auto iter = find_insert_location(key); +- +- if (iter == m_elements.end() || key != iter->first) +- { +- return m_elements.insert(iter, std::pair(key, value()))->second; +- } +- +- return iter->second; +- } ++ json::value& operator[](const utility::string_t& key); + + /// + /// Gets an iterator to an element of a JSON object. +--- a/Release/src/json/json.cpp ++++ b/Release/src/json/json.cpp +@@ -135,6 +135,14 @@ + { + } + ++#ifdef ENABLE_JSON_VALUE_VISUALIZER ++web::json::value::value(std::unique_ptr v, value_type kind) : m_value(std::move(v)), m_kind(kind) ++#else ++web::json::value::value(std::unique_ptr v) : m_value(std::move(v)) ++#endif ++{ ++} ++ + web::json::value::value(const value& other) + : m_value(other.m_value->_copy_value()) + #ifdef ENABLE_JSON_VALUE_VISUALIZER +@@ -495,3 +503,67 @@ + #endif + return instance; + } ++ ++web::json::array::array() : m_elements() {} ++web::json::array::array(size_type size) : m_elements(size) {} ++web::json::array::array(storage_type elements) : m_elements(std::move(elements)) {} ++ ++web::json::array::iterator web::json::array::erase(web::json::array::iterator position) ++{ ++ return m_elements.erase(position); ++} ++ ++void web::json::array::erase(web::json::array::size_type index) ++{ ++ if (index >= m_elements.size()) ++ { ++ throw json_exception("index out of bounds"); ++ } ++ m_elements.erase(m_elements.begin() + index); ++} ++ ++json::value& web::json::array::operator[](web::json::array::size_type index) ++{ ++ msl::safeint3::SafeInt nMinSize(index); ++ nMinSize += 1; ++ msl::safeint3::SafeInt nlastSize(m_elements.size()); ++ if (nlastSize < nMinSize) m_elements.resize((size_type)nMinSize); ++ ++ return m_elements[index]; ++} ++ ++web::json::object::object(bool keep_order) : m_elements(), m_keep_order(keep_order) {} ++web::json::object::object(storage_type elements, bool keep_order) : m_elements(std::move(elements)), m_keep_order(keep_order) ++{ ++ if (!keep_order) ++ { ++ sort(m_elements.begin(), m_elements.end(), compare_pairs); ++ } ++} ++web::json::object::iterator web::json::object::erase(iterator position) ++{ ++ return m_elements.erase(position); ++} ++ ++void web::json::object::erase(const utility::string_t& key) ++{ ++ auto iter = find_by_key(key); ++ if (iter == m_elements.end()) ++ { ++ throw web::json::json_exception("Key not found"); ++ } ++ ++ m_elements.erase(iter); ++} ++ ++json::value& web::json::object::operator[](const utility::string_t& key) ++{ ++ auto iter = find_insert_location(key); ++ ++ if (iter == m_elements.end() || key != iter->first) ++ { ++ return m_elements.insert(iter, std::pair(key, value()))->second; ++ } ++ ++ return iter->second; ++}