Skip to content

Commit c695465

Browse files
committed
Merge branch 'apple' of https://git01.codeplex.com/casablanca into apple
Conflicts: Release/src/utilities/asyncrt_utils.cpp
2 parents a534627 + 5534f25 commit c695465

File tree

7 files changed

+97
-39
lines changed

7 files changed

+97
-39
lines changed

Release/include/cpprest/json.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ namespace web { namespace json
268268
/// <returns><c>true</c> if the value is a number value, <c>false</c> otherwise</returns>
269269
bool is_number() const { return type() == Number; }
270270

271+
/// <summary>
272+
/// Is the current value represented as an integer number value?
273+
/// </summary>
274+
/// <remarks>
275+
/// Note that if a json value is a number but represented as a double it can still
276+
/// be retrieved as a integer using as_integer(), however the value will be truncated.
277+
/// </remarks>
278+
/// <returns><c>true</c> if the value is an integer value, <c>false</c> otherwise.</returns>
279+
_ASYNCRTIMP bool is_integer() const ;
280+
281+
/// <summary>
282+
/// Is the current value represented as an double number value?
283+
/// </summary>
284+
/// <remarks>
285+
/// Note that if a json value is a number but represented as a int it can still
286+
/// be retrieved as a double using as_double().
287+
/// </remarks>
288+
/// <returns><c>true</c> if the value is an double value, <c>false</c> otherwise.</returns>
289+
_ASYNCRTIMP bool is_double() const ;
290+
271291
/// <summary>
272292
/// Is the current value a Boolean value?
273293
/// </summary>
@@ -568,6 +588,9 @@ namespace web { namespace json
568588

569589
virtual json::value::value_type type() const { return json::value::Null; }
570590

591+
virtual bool is_integer() const { throw json_exception(_XPLATSTR("not a number")); }
592+
virtual bool is_double() const { throw json_exception(_XPLATSTR("not a number")); }
593+
571594
virtual double as_double() const { throw json_exception(_XPLATSTR("not a number")); }
572595
virtual int32_t as_integer() const { throw json_exception(_XPLATSTR("not a number")); }
573596
virtual bool as_bool() const { throw json_exception(_XPLATSTR("not a boolean")); }
@@ -647,6 +670,9 @@ namespace web { namespace json
647670

648671
virtual json::value::value_type type() const { return json::value::Number; }
649672

673+
virtual bool is_integer() const { return m_was_int; }
674+
virtual bool is_double() const { return !m_was_int; }
675+
650676
virtual double as_double() const { return m_was_int ? static_cast<double>(m_intval) : m_value; }
651677
virtual int32_t as_integer() const { return m_was_int ? m_intval : static_cast<int32_t>(m_value); }
652678

Release/include/cpprest/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
* ==--==
1717
*/
18-
#define CPPREST_VERSION_REVISION 0
18+
#define CPPREST_VERSION_REVISION 1
1919
#define CPPREST_VERSION_MINOR 3
2020
#define CPPREST_VERSION_MAJOR 1
2121

Release/src/json/json.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,24 @@ web::json::details::_Object::_Object(const _Object& other):web::json::details::_
435435

436436
web::json::value::value_type json::value::type() const { return m_value->type(); }
437437

438+
bool json::value::is_integer() const
439+
{
440+
if(!is_number())
441+
{
442+
return false;
443+
}
444+
return m_value->is_integer();
445+
}
446+
447+
bool json::value::is_double() const
448+
{
449+
if(!is_number())
450+
{
451+
return false;
452+
}
453+
return m_value->is_double();
454+
}
455+
438456
json::value& web::json::details::_Object::index(const utility::string_t &key)
439457
{
440458
map_fields();

Release/src/utilities/asyncrt_utils.cpp

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ using namespace Platform;
3030
using namespace Windows::Storage::Streams;
3131
#endif // #if !defined(__cplusplus_winrt)
3232

33-
#if !defined(_MS_WINDOWS)
33+
#if defined(_MS_WINDOWS)
34+
#include <regex>
35+
#else
3436
#include <boost/date_time/posix_time/posix_time.hpp>
3537
#include <boost/date_time/posix_time/posix_time_io.hpp>
36-
#ifdef __APPLE__
38+
#ifndef __APPLE__
3739
// GCC 4.8 does not support regex, use boost. TODO: switch to std::regex in GCC 4.9
3840
// Clang already supports std::regex
3941
#include <boost/regex.hpp>
@@ -558,24 +560,25 @@ utility::string_t datetime::to_string(date_format format) const
558560
}
559561
else if ( format == ISO_8601 )
560562
{
563+
const size_t buffSize = 64;
561564
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
562-
TCHAR dateStr[18] = {0};
563-
status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, "yyyy-MM-dd", dateStr, sizeof(dateStr) / sizeof(wchar_t));
565+
TCHAR dateStr[buffSize] = {0};
566+
status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, "yyyy-MM-dd", dateStr, buffSize);
564567
#else
565-
wchar_t dateStr[18] = {0};
566-
status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL);
568+
wchar_t dateStr[buffSize] = {0};
569+
status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL);
567570
#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
568571
if (status == 0)
569572
{
570573
throw utility::details::create_system_error(GetLastError());
571574
}
572575

573576
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
574-
TCHAR timeStr[10] = {0};
575-
status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, "HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t));
577+
TCHAR timeStr[buffSize] = {0};
578+
status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, "HH':'mm':'ss", timeStr, buffSize);
576579
#else
577-
wchar_t timeStr[10] = {0};
578-
status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t));
580+
wchar_t timeStr[buffSize] = {0};
581+
status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize);
579582
#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
580583
if (status == 0)
581584
{
@@ -636,7 +639,7 @@ utility::string_t datetime::to_string(date_format format) const
636639
}
637640

638641
#ifdef _MS_WINDOWS
639-
bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, double seconds, datetime * pdt)
642+
bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, uint64_t seconds, datetime * pdt)
640643
{
641644
SYSTEMTIME* psysTime = (SYSTEMTIME*)pvsysTime;
642645
FILETIME fileTime;
@@ -648,8 +651,7 @@ bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, double seconds,
648651
largeInt.HighPart = fileTime.dwHighDateTime;
649652

650653
// Add hundredths of nanoseconds
651-
uint64_t hn = (uint64_t)(seconds * _secondTicks);
652-
largeInt.QuadPart += hn;
654+
largeInt.QuadPart += seconds;
653655

654656
*pdt = datetime(largeInt.QuadPart);
655657
return true;
@@ -680,6 +682,9 @@ uint64_t timeticks_from_second(const utility::string_t& str)
680682
/// </summary>
681683
datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
682684
{
685+
// avoid floating point math to preserve precision
686+
uint64_t ufrac_second = 0;
687+
683688
#ifdef _MS_WINDOWS
684689
datetime result;
685690
if ( format == RFC_1123 )
@@ -708,7 +713,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
708713
if (loc != monthnames+12)
709714
{
710715
sysTime.wMonth = (short) ((loc - monthnames) + 1);
711-
if (system_type_to_datetime(&sysTime, 0.0, &result))
716+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
712717
{
713718
return result;
714719
}
@@ -719,23 +724,33 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
719724
{
720725
// Unlike FILETIME, SYSTEMTIME does not have enough precision to hold seconds in 100 nanosecond
721726
// increments. Therefore, start with seconds and milliseconds set to 0, then add them separately
722-
// from this double:
723-
double seconds;
727+
728+
// Try to extract the fractional second from the timestamp
729+
std::wregex r_frac_second(L"(.+)(\\.\\d+)(Z$)");
730+
std::wsmatch m;
731+
732+
std::wstring input(dateString);
733+
if (std::regex_search(dateString, m, r_frac_second))
734+
{
735+
auto frac = m[2].str(); // this is the fractional second
736+
ufrac_second = timeticks_from_second(frac);
737+
input = m[1].str() + m[3].str();
738+
}
724739

725740
{
726741
SYSTEMTIME sysTime = { 0 };
727-
const wchar_t * formatString = L"%4d-%2d-%2dT%2d:%2d:%lfZ";
728-
auto n = swscanf_s(dateString.c_str(), formatString,
742+
const wchar_t * formatString = L"%4d-%2d-%2dT%2d:%2d:%2dZ";
743+
auto n = swscanf_s(input.c_str(), formatString,
729744
&sysTime.wYear,
730745
&sysTime.wMonth,
731746
&sysTime.wDay,
732747
&sysTime.wHour,
733748
&sysTime.wMinute,
734-
&seconds);
749+
&sysTime.wSecond);
735750

736751
if (n == 3 || n == 6)
737752
{
738-
if (system_type_to_datetime(&sysTime, seconds, &result))
753+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
739754
{
740755
return result;
741756
}
@@ -745,12 +760,12 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
745760
SYSTEMTIME sysTime = {0};
746761
DWORD date = 0;
747762

748-
const wchar_t * formatString = L"%8dT%2d:%2d:%lfZ";
749-
auto n = swscanf_s(dateString.c_str(), formatString,
763+
const wchar_t * formatString = L"%8dT%2d:%2d:%2dZ";
764+
auto n = swscanf_s(input.c_str(), formatString,
750765
&date,
751766
&sysTime.wHour,
752767
&sysTime.wMinute,
753-
&seconds);
768+
&sysTime.wSecond);
754769

755770
if (n == 1 || n == 4)
756771
{
@@ -760,7 +775,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
760775
date /= 100;
761776
sysTime.wYear = (WORD)date;
762777

763-
if (system_type_to_datetime(&sysTime, seconds, &result))
778+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
764779
{
765780
return result;
766781
}
@@ -769,19 +784,18 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
769784
{
770785
SYSTEMTIME sysTime = {0};
771786
GetSystemTime(&sysTime); // Fill date portion with today's information
772-
// Zero out second -- we will use the double for that
773787
sysTime.wSecond = 0;
774788
sysTime.wMilliseconds = 0;
775789

776-
const wchar_t * formatString = L"%2d:%2d:%lfZ";
777-
auto n = swscanf_s(dateString.c_str(), formatString,
790+
const wchar_t * formatString = L"%2d:%2d:%2dZ";
791+
auto n = swscanf_s(input.c_str(), formatString,
778792
&sysTime.wHour,
779793
&sysTime.wMinute,
780-
&seconds);
794+
&sysTime.wSecond);
781795

782796
if (n == 3)
783797
{
784-
if (system_type_to_datetime(&sysTime, seconds, &result))
798+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
785799
{
786800
return result;
787801
}
@@ -795,9 +809,6 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
795809

796810
struct tm output = tm();
797811

798-
// avoid floating point math to preserve precision
799-
uint64_t ufrac_second = 0;
800-
801812
if ( format == RFC_1123 )
802813
{
803814
strptime(input.data(), "%a, %d %b %Y %H:%M:%S GMT", &output);
@@ -825,8 +836,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
825836
ufrac_second = timeticks_from_second(frac);
826837
input = m[1].str() + m[3].str();
827838
}
828-
#endif
829-
839+
830840
auto result = strptime(input.data(), "%Y-%m-%dT%H:%M:%SZ", &output);
831841

832842
if ( result == nullptr )

Release/tests/Common/TestRunner/test_runner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static std::vector<std::string> get_matching_binaries(const std::string &dllName
200200

201201
static std::multimap<std::string, std::string> g_properties;
202202
static std::vector<std::string> g_test_binaries;
203-
static int g_individual_test_timeout = 100 * 60000 * 3;
203+
static int g_individual_test_timeout = 60000 * 3;
204204

205205
static int parse_command_line(int argc, char **argv)
206206
{

Release/tests/Functional/json/construction_tests.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,12 @@ TEST(constructor_overloads)
157157
VERIFY_IS_TRUE(v0.is_null());
158158
VERIFY_ARE_EQUAL(v1.type(), json::value::Number);
159159
VERIFY_IS_TRUE(v1.is_number());
160+
VERIFY_IS_TRUE(v1.is_integer());
161+
VERIFY_IS_FALSE(v1.is_double());
160162
VERIFY_ARE_EQUAL(v2.type(), json::value::Number);
161163
VERIFY_IS_TRUE(v2.is_number());
164+
VERIFY_IS_TRUE(v2.is_double());
165+
VERIFY_IS_FALSE(v2.is_integer());
162166
VERIFY_ARE_EQUAL(v3.type(), json::value::Boolean);
163167
VERIFY_IS_TRUE(v3.is_boolean());
164168
VERIFY_ARE_EQUAL(v4.type(), json::value::String);

Release/tests/Functional/utils/base64.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,12 @@ TEST(bad_decode, "Ignore:Linux", "glib does not reject any of these inputs")
245245

246246
TEST(large_string)
247247
{
248-
size_t size = 128*1024;
248+
const size_t size = 64*1024;
249249

250-
std::vector<unsigned char> data;
250+
std::vector<unsigned char> data(size);
251251
for (auto i = 0u; i < size; ++i)
252252
{
253-
data.push_back((unsigned char)(rand() & 0xFF));
253+
data[i] = (unsigned char)(rand() & 0xFF);
254254
}
255255

256256
auto string = utility::conversions::to_base64(data);

0 commit comments

Comments
 (0)