Skip to content

Commit 4f3b56e

Browse files
committed
Merge branch 'development' of https://git01.codeplex.com/casablanca into json_control_chars
2 parents 558a3d9 + dad3cbc commit 4f3b56e

File tree

8 files changed

+302
-59
lines changed

8 files changed

+302
-59
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>
@@ -843,6 +876,30 @@ namespace json
843876
return m_elements.crend();
844877
}
845878

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

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

10501134
return iter->second;
10511135
}
@@ -1058,9 +1142,10 @@ namespace json
10581142
const json::value& at(const utility::string_t& key) const
10591143
{
10601144
auto iter = find_by_key(key);
1061-
1062-
if (iter == m_elements.end() || key != (iter->first))
1145+
if (iter == m_elements.end())
1146+
{
10631147
throw web::json::json_exception(_XPLATSTR("Key not found"));
1148+
}
10641149

10651150
return iter->second;
10661151
}
@@ -1072,10 +1157,12 @@ namespace json
10721157
/// <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>
10731158
json::value& operator[](const utility::string_t& key)
10741159
{
1075-
auto iter = find_by_key(key);
1160+
auto iter = find_insert_location(key);
10761161

1077-
if (iter == m_elements.end() || key != (iter->first))
1162+
if (iter == m_elements.end() || key != iter->first)
1163+
{
10781164
return m_elements.insert(iter, std::pair<utility::string_t, value>(key, value()))->second;
1165+
}
10791166

10801167
return iter->second;
10811168
}
@@ -1087,7 +1174,7 @@ namespace json
10871174
/// <returns>A const iterator to the value kept in the field.</returns>
10881175
const_iterator find(const utility::string_t& key) const
10891176
{
1090-
return find_internal(key);
1177+
return find_by_key(key);
10911178
}
10921179

10931180
/// <summary>
@@ -1118,7 +1205,7 @@ namespace json
11181205
return p1.first < key;
11191206
}
11201207

1121-
storage_type::const_iterator find_by_key(const utility::string_t& key) const
1208+
storage_type::iterator find_insert_location(const utility::string_t &key)
11221209
{
11231210
if (m_keep_order)
11241211
{
@@ -1133,7 +1220,7 @@ namespace json
11331220
}
11341221
}
11351222

1136-
storage_type::iterator find_by_key(const utility::string_t& key)
1223+
storage_type::const_iterator find_by_key(const utility::string_t& key) const
11371224
{
11381225
if (m_keep_order)
11391226
{
@@ -1144,37 +1231,22 @@ namespace json
11441231
}
11451232
else
11461233
{
1147-
return std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1234+
auto iter = std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1235+
if (iter != m_elements.end() && key != iter->first)
1236+
{
1237+
return m_elements.end();
1238+
}
1239+
return iter;
11481240
}
11491241
}
11501242

1151-
const json::value& at_internal(const utility::string_t& key) const
1152-
{
1153-
auto iter = find_by_key(key);
1154-
1155-
if (iter == m_elements.end() || key != (iter->first))
1156-
throw web::json::json_exception(_XPLATSTR("Key not found"));
1157-
1158-
return iter->second;
1159-
}
1160-
1161-
const_iterator find_internal(const utility::string_t& key) const
1162-
{
1163-
auto iter = find_by_key(key);
1164-
1165-
if (iter != m_elements.end() && key != (iter->first))
1166-
return m_elements.end();
1167-
1168-
return iter;
1169-
}
1170-
1171-
iterator find_internal(const utility::string_t& key)
1243+
storage_type::iterator find_by_key(const utility::string_t& key)
11721244
{
1173-
auto iter = find_by_key(key);
1174-
1175-
if (iter != m_elements.end() && key != (iter->first))
1245+
auto iter = find_insert_location(key);
1246+
if (iter != m_elements.end() && key != iter->first)
1247+
{
11761248
return m_elements.end();
1177-
1249+
}
11781250
return iter;
11791251
}
11801252

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: 25 additions & 0 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);
@@ -415,6 +430,16 @@ bool json::value::operator==(const json::value &other) const
415430
__assume(0);
416431
}
417432

433+
void web::json::value::erase(size_t index)
434+
{
435+
return this->as_array().erase(index);
436+
}
437+
438+
void web::json::value::erase(const utility::string_t &key)
439+
{
440+
return this->as_object().erase(key);
441+
}
442+
418443
// at() overloads
419444
web::json::value& web::json::value::at(size_t index)
420445
{

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);

Release/tests/functional/json/json_numbers_tests.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ void test_int64(int64_t number)
6161
json::value num = json::value::parse(ss);
6262
VERIFY_ARE_EQUAL(number, num.as_number().to_int64());
6363
VERIFY_IS_TRUE(num.is_integer());
64+
num = json::value::number(number);
65+
VERIFY_ARE_EQUAL(number, num.as_number().to_int64());
66+
VERIFY_IS_TRUE(num.is_integer());
6467

65-
// Check that the number is convertable to signed int64
68+
// Check that the number is convertible to signed int64
6669
VERIFY_IS_TRUE(num.as_number().is_int64());
6770

6871
// Check for other integral conversions
@@ -103,8 +106,11 @@ void test_int64(uint64_t number)
103106
json::value num = json::value::parse(ss);
104107
VERIFY_ARE_EQUAL(number, num.as_number().to_uint64());
105108
VERIFY_IS_TRUE(num.is_integer());
109+
num = json::value::number(number);
110+
VERIFY_ARE_EQUAL(number, num.as_number().to_uint64());
111+
VERIFY_IS_TRUE(num.is_integer());
106112

107-
// Check that the number is convertable to unsigned int64
113+
// Check that the number is convertible to unsigned int64
108114
VERIFY_IS_TRUE(num.as_number().is_uint64());
109115

110116
// Check for other integral conversions
@@ -195,11 +201,14 @@ TEST(parsing_doubles_setlocale, "Ignore:Android", "Locale not supported on Andro
195201
#else
196202
std::string changedLocale("fr_FR.UTF-8");
197203
#endif
198-
setlocale(LC_ALL, changedLocale.c_str());
199204

200-
test_double(1.91563);
201-
test_double(2.0e93);
202-
setlocale(LC_ALL, "C");
205+
// If locale isn't installed on system just silently pass.
206+
if (setlocale(LC_ALL, changedLocale.c_str()) != nullptr)
207+
{
208+
test_double(1.91563);
209+
test_double(2.0e93);
210+
setlocale(LC_ALL, "C");
211+
}
203212
}
204213

205214
TEST(parsing_very_large_doubles)

0 commit comments

Comments
 (0)