C++ Rest SDK
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
asyncrt_utils.h
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 
50 namespace utility
51 {
52 
53 // Left over from VS2010 support, remains to avoid breaking.
54 typedef std::chrono::seconds seconds;
55 
57 namespace timespan
58 {
63  _ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs);
64 
69  _ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t &timespanString);
70 }
71 
73 namespace conversions
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 
94  _ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string &s);
95 
101  _ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string &s);
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:
229  _ASYNCRTIMP scoped_c_thread_locale();
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 {
365  return utility::conversions::to_string_t(create_error_code(errorCode).message());
366 }
367 
368 }
369 
370 class datetime
371 {
372 public:
373  typedef uint64_t interval_type;
374 
378  enum date_format { RFC_1123, ISO_8601 };
379 
383  static _ASYNCRTIMP datetime __cdecl utc_now();
384 
388  enum:interval_type { utc_timestamp_invalid = static_cast<interval_type>(-1) };
389 
394  static interval_type utc_timestamp()
395  {
396  const auto seconds = utc_now().to_interval() / _secondTicks;
397  if (seconds >= 11644473600LL)
398  {
399  return seconds - 11644473600LL;
400  }
401  else
402  {
403  return utc_timestamp_invalid;
404  }
405  }
406 
407  datetime() : m_interval(0)
408  {
409  }
410 
415  static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
416 
420  _ASYNCRTIMP utility::string_t to_string(date_format format = RFC_1123) const;
421 
425  interval_type to_interval() const
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
511 class cmp
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 
542 inline int operator- (datetime t1, datetime t2)
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 
568  nonce_generator(int length=default_length) :
569  m_random(static_cast<unsigned int>(utility::datetime::utc_timestamp())),
570  m_length(length)
571  {}
572 
578  _ASYNCRTIMP utility::string_t generate();
579 
584  int length() const { return m_length; }
585 
590  void set_length(int length) { m_length = length; }
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 &timestring, 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 &timespanString)
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