1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * ==--==
17 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18 *
19 * Various common utilities.
20 *
21 * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22 *
23 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24 ****/
25
26 #pragma once
27
28 #include <string>
29 #include <vector>
30 #include <cstdint>
31 #include <system_error>
32 #include <random>
33 #include <locale.h>
34
35 #include "pplx/pplxtasks.h"
36 #include "cpprest/details/basic_types.h"
37
38 #if !defined(_WIN32) || (_MSC_VER >= 1700)
39 #include <chrono>
40 #endif
41
42 #ifndef _WIN32
43 #include <boost/algorithm/string.hpp>
44 #if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
45 #include <xlocale.h>
46 #endif
47 #endif
48
51 {
52
53 // Left over from VS2010 support, remains to avoid breaking.
54 typedef std::chrono::seconds seconds;
55
58 {
64
70 }
71
74 {
80 _ASYNCRTIMP std::string __cdecl
utf16_to_utf8(
const utf16string &w);
81
87 _ASYNCRTIMP utf16string __cdecl
utf8_to_utf16(
const std::string &s);
88
95
102
108 _ASYNCRTIMP utf8string __cdecl
latin1_to_utf8(
const std::string &s);
109
115 _ASYNCRTIMP utility::string_t __cdecl
to_string_t(std::string &&s);
116
122 _ASYNCRTIMP utility::string_t __cdecl
to_string_t(utf16string &&s);
123
129 _ASYNCRTIMP utility::string_t __cdecl
to_string_t(
const std::string &s);
130
136 _ASYNCRTIMP utility::string_t __cdecl
to_string_t(
const utf16string &s);
137
143 _ASYNCRTIMP utf16string __cdecl
to_utf16string(
const std::string &value);
144
150 _ASYNCRTIMP utf16string __cdecl
to_utf16string(utf16string value);
151
157 _ASYNCRTIMP std::string __cdecl
to_utf8string(std::string value);
158
164 _ASYNCRTIMP std::string __cdecl
to_utf8string(
const utf16string &value);
165
169 _ASYNCRTIMP utility::string_t __cdecl
to_base64(
const std::vector<unsigned char>& data);
170
174 _ASYNCRTIMP utility::string_t __cdecl
to_base64(uint64_t data);
175
179 _ASYNCRTIMP std::vector<unsigned char> __cdecl
from_base64(
const utility::string_t& str);
180
181 template <typename Source>
182 utility::string_t print_string(const Source &val, const std::locale &loc)
183 {
184 utility::ostringstream_t oss;
185 oss.imbue(loc);
186 oss << val;
187 if (oss.bad())
188 {
189 throw std::bad_cast();
190 }
191 return oss.str();
192 }
193
194 template <typename Source>
195 utility::string_t print_string(const Source &val)
196 {
197 return print_string(val, std::locale());
198 }
199
200 template <typename Target>
201 Target scan_string(const utility::string_t &str, const std::locale &loc)
202 {
203 Target t;
204 utility::istringstream_t iss(str);
205 iss.imbue(loc);
206 iss >> t;
207 if (iss.bad())
208 {
209 throw std::bad_cast();
210 }
211 return t;
212 }
213
214 template <typename Target>
215 Target scan_string(const utility::string_t &str)
216 {
217 return scan_string<Target>(str, std::locale());
218 }
219 }
220
221 namespace details
222 {
227 {
228 public:
230 _ASYNCRTIMP ~scoped_c_thread_locale();
231
232 #if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
233 #ifdef _WIN32
234 typedef _locale_t xplat_locale;
235 #else
236 typedef locale_t xplat_locale;
237 #endif
238
239 static _ASYNCRTIMP xplat_locale __cdecl c_locale();
240 #endif
241 private:
242 #ifdef _WIN32
243 std::string m_prevLocale;
244 int m_prevThreadSetting;
245 #elif !(defined(ANDROID) || defined(__ANDROID__))
246 locale_t m_prevLocale;
247 #endif
248 scoped_c_thread_locale(const scoped_c_thread_locale &);
249 scoped_c_thread_locale & operator=(const scoped_c_thread_locale &);
250 };
251
256 inline bool __cdecl is_alnum(char ch)
257 {
258 return (ch >= '0' && ch <= '9')
259 || (ch >= 'A' && ch <= 'Z')
260 || (ch >= 'a' && ch <= 'z');
261 }
262
267 template <typename _Type>
268 std::unique_ptr<_Type> make_unique() {
269 return std::unique_ptr<_Type>(new _Type());
270 }
271
272 template <typename _Type, typename _Arg1>
273 std::unique_ptr<_Type> make_unique(_Arg1&& arg1) {
274 return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1)));
275 }
276
277 template <typename _Type, typename _Arg1, typename _Arg2>
278 std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2) {
279 return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2)));
280 }
281
282 template <typename _Type, typename _Arg1, typename _Arg2, typename _Arg3>
283 std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3) {
284 return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3)));
285 }
286
287 template <typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4>
288 std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4) {
289 return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3), std::forward<_Arg4>(arg4)));
290 }
291
298 inline bool str_icmp(const utility::string_t &left, const utility::string_t &right)
299 {
300 #ifdef _WIN32
301 return _wcsicmp(left.c_str(), right.c_str()) == 0;
302 #else
303 return boost::iequals(left, right);
304 #endif
305 }
306
307 #ifdef _WIN32
308
312 class windows_category_impl : public std::error_category
313 {
314 public:
315 virtual const char *name() const CPPREST_NOEXCEPT { return "windows"; }
316
317 _ASYNCRTIMP virtual std::string message(int errorCode) const CPPREST_NOEXCEPT;
318
319 _ASYNCRTIMP virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT;
320 };
321
326 _ASYNCRTIMP const std::error_category & __cdecl windows_category();
327
328 #else
329
334 _ASYNCRTIMP const std::error_category & __cdecl linux_category();
335
336 #endif
337
341 _ASYNCRTIMP const std::error_category & __cdecl platform_category();
342
346 inline std::system_error __cdecl create_system_error(unsigned long errorCode)
347 {
348 std::error_code code((int)errorCode, platform_category());
349 return std::system_error(code, code.message());
350 }
351
355 inline std::error_code __cdecl create_error_code(unsigned long errorCode)
356 {
357 return std::error_code((int)errorCode, platform_category());
358 }
359
363 inline utility::string_t __cdecl create_error_message(unsigned long errorCode)
364 {
366 }
367
368 }
369
371 {
372 public:
373 typedef uint64_t interval_type;
374
379
384
388 enum:interval_type { utc_timestamp_invalid = static_cast<interval_type>(-1) };
389
395 {
397 if (seconds >= 11644473600LL)
398 {
399 return seconds - 11644473600LL;
400 }
401 else
402 {
403 return utc_timestamp_invalid;
404 }
405 }
406
408 {
409 }
410
415 static _ASYNCRTIMP datetime __cdecl
from_string(
const utility::string_t& timestring,
date_format format = RFC_1123);
416
421
426 {
427 return m_interval;
428 }
429
430 datetime operator- (interval_type value)
const
431 {
432 return datetime(m_interval - value);
433 }
434
435 datetime operator+ (interval_type value) const
436 {
437 return datetime(m_interval + value);
438 }
439
440 bool operator== (datetime dt) const
441 {
442 return m_interval == dt.m_interval;
443 }
444
445 bool operator!= (const datetime& dt) const
446 {
447 return !(*this == dt);
448 }
449
450 static interval_type from_milliseconds(unsigned int milliseconds)
451 {
452 return milliseconds*_msTicks;
453 }
454
455 static interval_type from_seconds(unsigned int seconds)
456 {
457 return seconds*_secondTicks;
458 }
459
460 static interval_type from_minutes(unsigned int minutes)
461 {
462 return minutes*_minuteTicks;
463 }
464
465 static interval_type from_hours(unsigned int hours)
466 {
467 return hours*_hourTicks;
468 }
469
470 static interval_type from_days(unsigned int days)
471 {
472 return days*_dayTicks;
473 }
474
475 bool is_initialized() const
476 {
477 return m_interval != 0;
478 }
479
480 private:
481
482 friend int operator- (datetime t1, datetime t2);
483
484 static const interval_type _msTicks = static_cast<interval_type>(10000);
485 static const interval_type _secondTicks = 1000*_msTicks;
486 static const interval_type _minuteTicks = 60*_secondTicks;
487 static const interval_type _hourTicks = 60*60*_secondTicks;
488 static const interval_type _dayTicks = 24*60*60*_secondTicks;
489
490
491 #ifdef _WIN32
492 // void* to avoid pulling in windows.h
493 static _ASYNCRTIMP bool __cdecl datetime::system_type_to_datetime(/*SYSTEMTIME*/ void* psysTime, uint64_t seconds, datetime * pdt);
494 #else
495 static datetime timeval_to_datetime(const timeval &time);
496 #endif
497
498 // Private constructor. Use static methods to create an instance.
499 datetime(interval_type interval) : m_interval(interval)
500 {
501 }
502
503 // Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
504 interval_type m_interval;
505 };
506
507 #ifndef _WIN32
508
509 // temporary workaround for the fact that
510 // utf16char is not fully supported in GCC
512 {
513 public:
514
515 static int icmp(std::string left, std::string right)
516 {
517 size_t i;
518 for (i = 0; i < left.size(); ++i)
519 {
520 if (i == right.size()) return 1;
521
522 auto l = cmp::tolower(left[i]);
523 auto r = cmp::tolower(right[i]);
524 if (l > r) return 1;
525 if (l < r) return -1;
526 }
527 if (i < right.size()) return -1;
528 return 0;
529 }
530
531 private:
532 static char tolower(char c)
533 {
534 if (c >= 'A' && c <= 'Z')
535 return static_cast<char>(c - 'A' + 'a');
536 return c;
537 }
538 };
539
540 #endif
541
543 {
544 auto diff = (t1.m_interval - t2.m_interval);
545
546 // Round it down to seconds
547 diff /= 10 * 1000 * 1000;
548
549 return static_cast<int>(diff);
550 }
551
556 {
557 public:
558
562 enum { default_length = 32 };
563
570 m_length(length)
571 {}
572
578 _ASYNCRTIMP utility::string_t generate();
579
585
591
592 private:
593 static const utility::string_t c_allowed_chars;
594 std::mt19937 m_random;
595 int m_length;
596 };
597
598 } // namespace utility;
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string &w)
Converts a UTF-16 string to a UTF-8 string.
_ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs)
Converts a timespan/interval in seconds to xml duration string as specified by http://www.w3.org/TR/xmlschema-2/#duration
Definition: asyncrt_utils.h:511
static _ASYNCRTIMP datetime __cdecl utc_now()
Returns the current UTC time.
Cross platform RAII container for setting thread local locale.
Definition: asyncrt_utils.h:226
_ASYNCRTIMP utility::string_t to_string(date_format format=RFC_1123) const
Returns a string representation of the datetime.
static interval_type utc_timestamp()
Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00. If time is before epoch...
Definition: asyncrt_utils.h:394
nonce_generator(int length=default_length)
Nonce generator constructor.
Definition: asyncrt_utils.h:568
Definition: asyncrt_utils.h:370
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector< unsigned char > &data)
Encode the given byte array into a base64 string
interval_type to_interval() const
Returns the integral time value.
Definition: asyncrt_utils.h:425
void set_length(int length)
Set length of the generated nonce string.
Definition: asyncrt_utils.h:590
_ASYNCRTIMP utf16string __cdecl utf8_to_utf16(const std::string &s)
Converts a UTF-8 string to a UTF-16
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t ×tring, date_format format=RFC_1123)
Creates datetime from a string representing time in UTC in RFC 1123 format.
int length() const
Get length of generated nonce string.
Definition: asyncrt_utils.h:584
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s)
Converts to a platform dependent Unicode string type.
date_format
Defines the supported date and time string formats.
Definition: asyncrt_utils.h:378
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string &value)
Converts to a UTF-16 from string.
_ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t ×panString)
Converts an xml duration to timespan/interval in seconds http://www.w3.org/TR/xmlschema-2/#duration ...
_ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string &s)
Converts a ASCII (us-ascii) string to a UTF-16 string.
Nonce string generator class.
Definition: asyncrt_utils.h:555
_ASYNCRTIMP std::vector< unsigned char > __cdecl from_base64(const utility::string_t &str)
Decode the given base64 string to a byte array
_ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string &s)
Converts a Latin1 (iso-8859-1) string to a UTF-16 string.
_ASYNCRTIMP utf8string __cdecl latin1_to_utf8(const std::string &s)
Converts a Latin1 (iso-8859-1) string to a UTF-8 string.
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value)
Converts to a UTF-8 string.
Various utilities for string conversions and date and time manipulation.
Definition: asyncrt_utils.h:50