Skip to content

Commit 874837e

Browse files
committed
Merge branch 'development' of https://git01.codeplex.com/casablanca into misc_json
2 parents c75f4d9 + f307c0a commit 874837e

File tree

9 files changed

+310
-65
lines changed

9 files changed

+310
-65
lines changed

Release/include/cpprest/json.h

Lines changed: 107 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,27 @@ namespace json
242242
/// <returns>A JSON number value</returns>
243243
static _ASYNCRTIMP value __cdecl number(int32_t value);
244244

245+
/// <summary>
246+
/// Creates a number value
247+
/// </summary>
248+
/// <param name="value">The C++ value to create a JSON value from</param>
249+
/// <returns>A JSON number value</returns>
250+
static _ASYNCRTIMP value __cdecl number(uint32_t value);
251+
252+
/// <summary>
253+
/// Creates a number value
254+
/// </summary>
255+
/// <param name="value">The C++ value to create a JSON value from</param>
256+
/// <returns>A JSON number value</returns>
257+
static _ASYNCRTIMP value __cdecl number(int64_t value);
258+
259+
/// <summary>
260+
/// Creates a number value
261+
/// </summary>
262+
/// <param name="value">The C++ value to create a JSON value from</param>
263+
/// <returns>A JSON number value</returns>
264+
static _ASYNCRTIMP value __cdecl number(uint64_t value);
265+
245266
/// <summary>
246267
/// Creates a Boolean value
247268
/// </summary>
@@ -543,6 +564,18 @@ namespace json
543564
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, use json::value::at() instead.")
544565
value get(const utility::string_t &key) const;
545566

567+
/// <summary>
568+
/// Erases an element of a JSON array. Throws if index is out of bounds.
569+
/// </summary>
570+
/// <param name="index">The index of the element to erase in the JSON array.</param>
571+
_ASYNCRTIMP void erase(size_t index);
572+
573+
/// <summary>
574+
/// Erases an element of a JSON object. Throws if the key doesn't exist.
575+
/// </summary>
576+
/// <param name="key">The key of the element to erase in the JSON object.</param>
577+
_ASYNCRTIMP void erase(const utility::string_t &key);
578+
546579
/// <summary>
547580
/// Accesses an element of a JSON array. Throws when index out of bounds.
548581
/// </summary>
@@ -841,6 +874,30 @@ namespace json
841874
return m_elements.crend();
842875
}
843876

877+
/// <summary>
878+
/// Deletes an element of the JSON array.
879+
/// </summary>
880+
/// <param name="position">A const_iterator to the element to delete.</param>
881+
/// <returns>Iterator to the new location of the element following the erased element.</returns>
882+
/// <remarks>GCC doesn't support erase with const_iterator on vector yet. In the future this should be changed.</remarks>
883+
iterator erase(iterator position)
884+
{
885+
return m_elements.erase(position);
886+
}
887+
888+
/// <summary>
889+
/// Deletes the element at an index of the JSON array.
890+
/// </summary>
891+
/// <param name="index">The index of the element to delete.</param>
892+
void erase(size_type index)
893+
{
894+
if (index >= m_elements.size())
895+
{
896+
throw json_exception(_XPLATSTR("index out of bounds"));
897+
}
898+
m_elements.erase(m_elements.begin() + index);
899+
}
900+
844901
/// <summary>
845902
/// Accesses an element of a JSON array. Throws when index out of bounds.
846903
/// </summary>
@@ -1031,6 +1088,32 @@ namespace json
10311088
return m_elements.crend();
10321089
}
10331090

1091+
/// <summary>
1092+
/// Deletes an element of the JSON object.
1093+
/// </summary>
1094+
/// <param name="position">A const_iterator to the element to delete.</param>
1095+
/// <returns>Iterator to the new location of the element following the erased element.</returns>
1096+
/// <remarks>GCC doesn't support erase with const_iterator on vector yet. In the future this should be changed.</remarks>
1097+
iterator erase(iterator position)
1098+
{
1099+
return m_elements.erase(position);
1100+
}
1101+
1102+
/// <summary>
1103+
/// Deletes an element of the JSON object. If the key doesn't exist, this method throws.
1104+
/// </summary>
1105+
/// <param name="key">The key of an element in the JSON object.</param>
1106+
void erase(const utility::string_t &key)
1107+
{
1108+
auto iter = find_by_key(key);
1109+
if (iter == m_elements.end())
1110+
{
1111+
throw web::json::json_exception(_XPLATSTR("Key not found"));
1112+
}
1113+
1114+
m_elements.erase(iter);
1115+
}
1116+
10341117
/// <summary>
10351118
/// Accesses an element of a JSON object. If the key doesn't exist, this method throws.
10361119
/// </summary>
@@ -1039,9 +1122,10 @@ namespace json
10391122
json::value& at(const utility::string_t& key)
10401123
{
10411124
auto iter = find_by_key(key);
1042-
1043-
if (iter == m_elements.end() || key != (iter->first))
1125+
if (iter == m_elements.end())
1126+
{
10441127
throw web::json::json_exception(_XPLATSTR("Key not found"));
1128+
}
10451129

10461130
return iter->second;
10471131
}
@@ -1054,9 +1138,10 @@ namespace json
10541138
const json::value& at(const utility::string_t& key) const
10551139
{
10561140
auto iter = find_by_key(key);
1057-
1058-
if (iter == m_elements.end() || key != (iter->first))
1141+
if (iter == m_elements.end())
1142+
{
10591143
throw web::json::json_exception(_XPLATSTR("Key not found"));
1144+
}
10601145

10611146
return iter->second;
10621147
}
@@ -1068,10 +1153,12 @@ namespace json
10681153
/// <returns>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.</returns>
10691154
json::value& operator[](const utility::string_t& key)
10701155
{
1071-
auto iter = find_by_key(key);
1156+
auto iter = find_insert_location(key);
10721157

1073-
if (iter == m_elements.end() || key != (iter->first))
1158+
if (iter == m_elements.end() || key != iter->first)
1159+
{
10741160
return m_elements.insert(iter, std::pair<utility::string_t, value>(key, value()))->second;
1161+
}
10751162

10761163
return iter->second;
10771164
}
@@ -1083,7 +1170,7 @@ namespace json
10831170
/// <returns>A const iterator to the value kept in the field.</returns>
10841171
const_iterator find(const utility::string_t& key) const
10851172
{
1086-
return find_internal(key);
1173+
return find_by_key(key);
10871174
}
10881175

10891176
/// <summary>
@@ -1114,7 +1201,7 @@ namespace json
11141201
return p1.first < key;
11151202
}
11161203

1117-
storage_type::const_iterator find_by_key(const utility::string_t& key) const
1204+
storage_type::iterator find_insert_location(const utility::string_t &key)
11181205
{
11191206
if (m_keep_order)
11201207
{
@@ -1129,7 +1216,7 @@ namespace json
11291216
}
11301217
}
11311218

1132-
storage_type::iterator find_by_key(const utility::string_t& key)
1219+
storage_type::const_iterator find_by_key(const utility::string_t& key) const
11331220
{
11341221
if (m_keep_order)
11351222
{
@@ -1140,37 +1227,22 @@ namespace json
11401227
}
11411228
else
11421229
{
1143-
return std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1230+
auto iter = std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1231+
if (iter != m_elements.end() && key != iter->first)
1232+
{
1233+
return m_elements.end();
1234+
}
1235+
return iter;
11441236
}
11451237
}
11461238

1147-
const json::value& at_internal(const utility::string_t& key) const
1148-
{
1149-
auto iter = find_by_key(key);
1150-
1151-
if (iter == m_elements.end() || key != (iter->first))
1152-
throw web::json::json_exception(_XPLATSTR("Key not found"));
1153-
1154-
return iter->second;
1155-
}
1156-
1157-
const_iterator find_internal(const utility::string_t& key) const
1158-
{
1159-
auto iter = find_by_key(key);
1160-
1161-
if (iter != m_elements.end() && key != (iter->first))
1162-
return m_elements.end();
1163-
1164-
return iter;
1165-
}
1166-
1167-
iterator find_internal(const utility::string_t& key)
1239+
storage_type::iterator find_by_key(const utility::string_t& key)
11681240
{
1169-
auto iter = find_by_key(key);
1170-
1171-
if (iter != m_elements.end() && key != (iter->first))
1241+
auto iter = find_insert_location(key);
1242+
if (iter != m_elements.end() && key != iter->first)
1243+
{
11721244
return m_elements.end();
1173-
1245+
}
11741246
return iter;
11751247
}
11761248

Release/src/http/listener/http_server_httpsys.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,14 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD
540540
{
541541
builder.set_query(uri::decode(builder.query()));
542542
}
543-
m_msg.set_request_uri(builder.to_uri());
543+
try
544+
{
545+
m_msg.set_request_uri(builder.to_uri());
546+
}
547+
catch(const uri_exception &e)
548+
{
549+
m_msg.reply(status_codes::BadRequest, e.what());
550+
}
544551
m_msg.set_method(parse_request_method(m_request));
545552
parse_http_headers(m_request->Headers, m_msg.headers());
546553

Release/src/json/json.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,21 @@ web::json::value web::json::value::number(int32_t value)
175175
return web::json::value(value);
176176
}
177177

178+
web::json::value web::json::value::number(uint32_t value)
179+
{
180+
return web::json::value(value);
181+
}
182+
183+
web::json::value web::json::value::number(int64_t value)
184+
{
185+
return web::json::value(value);
186+
}
187+
188+
web::json::value web::json::value::number(uint64_t value)
189+
{
190+
return web::json::value(value);
191+
}
192+
178193
web::json::value web::json::value::boolean(bool value)
179194
{
180195
return web::json::value(value);
@@ -340,11 +355,13 @@ bool web::json::number::is_int64() const
340355

341356
bool web::json::details::_String::has_escape_chars(const _String &str)
342357
{
343-
static const std::array<::utility::string_t::value_type, 34> escapes =
344-
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 0x00 - 0x1F */ '\"', '\\' };
345-
346-
// Provide the range otherwise find_first_of will think the first null terminator character is the end.
347-
return str.m_string.find_first_of(escapes.data(), 0, escapes.size()) != utility::string_t::npos;
358+
return std::any_of(std::begin(str.m_string), std::end(str.m_string), [](utility::string_t::value_type const x)
359+
{
360+
if (x >= 0 && x <= 31) { return true; }
361+
if (x == '"') { return true; }
362+
if (x == '\\') { return true; }
363+
return false;
364+
});
348365
}
349366

350367
web::json::value::value_type json::value::type() const { return m_value->type(); }
@@ -410,6 +427,16 @@ bool json::value::operator==(const json::value &other) const
410427
__assume(0);
411428
}
412429

430+
void web::json::value::erase(size_t index)
431+
{
432+
return this->as_array().erase(index);
433+
}
434+
435+
void web::json::value::erase(const utility::string_t &key)
436+
{
437+
return this->as_object().erase(key);
438+
}
439+
413440
// at() overloads
414441
web::json::value& web::json::value::at(size_t index)
415442
{

Release/src/json/json_serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void web::json::details::append_escape_string(std::basic_string<CharType>& str,
111111
// If a control character then must unicode escaped.
112112
if (ch >= 0 && ch <= 0x1F)
113113
{
114-
static const std::array<CharType, 16> intToHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
114+
static const std::array<CharType, 16> intToHex = { { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' } };
115115
str += '\\';
116116
str += 'u';
117117
str += '0';

Release/tests/functional/http/client/building_request_tests.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,22 @@ TEST_FIXTURE(uri_address, set_body_with_charset)
250250

251251
TEST_FIXTURE(uri_address, set_content_length_locale, "Ignore:Android", "Locale unsupported on Android")
252252
{
253+
std::locale changedLocale;
254+
try
255+
{
253256
#ifdef _WIN32
254-
std::string changedLocale("fr-FR");
257+
changedLocale = std::locale("fr-FR");
255258
#else
256-
std::string changedLocale("fr_FR.UTF-8");
259+
changedLocale = std::locale("fr_FR.UTF-8");
257260
#endif
261+
}
262+
catch (const std::exception &)
263+
{
264+
// Silently pass if locale isn't installed on the machine.
265+
return;
266+
}
258267

259-
tests::common::utilities::locale_guard loc(std::locale(changedLocale.c_str()));
268+
tests::common::utilities::locale_guard loc(changedLocale);
260269

261270
http_request req(methods::PUT);
262271
req.headers().set_content_length(1000);
@@ -276,12 +285,22 @@ TEST_FIXTURE(uri_address, set_port_locale, "Ignore:Android", "Locale unsupported
276285
});
277286

278287
{
288+
std::locale changedLocale;
289+
try
290+
{
279291
#ifdef _WIN32
280-
std::string changedLocale("fr-FR");
292+
changedLocale = std::locale("fr-FR");
281293
#else
282-
std::string changedLocale("fr_FR.UTF-8");
294+
changedLocale = std::locale("fr_FR.UTF-8");
283295
#endif
284-
tests::common::utilities::locale_guard loc(std::locale(changedLocale.c_str()));
296+
}
297+
catch (const std::exception &)
298+
{
299+
// Silently pass if locale isn't installed on machine.
300+
return;
301+
}
302+
303+
tests::common::utilities::locale_guard loc(changedLocale);
285304
http_request msg(methods::PUT);
286305
msg.set_body(data);
287306
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK);

0 commit comments

Comments
 (0)