root/core/ttypes.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. num_digits_in_base10
  2. uint64ToBufferUnsafe
  3. folly_ascii_to_int
  4. ascii_to_int_baseline
  5. tostring
  6. tostring
  7. tostring
  8. tostring_zero_pad_right_justify
  9. tostring
  10. noexcept
  11. noexcept
  12. noexcept
  13. tostring
  14. tostring
  15. tostring
  16. tostring
  17. fromstring
  18. noexcept
  19. noexcept
  20. noexcept
  21. delete_ptr
  22. toupper
  23. tolower
  24. toupper
  25. tolower

   1 #ifndef libjmmcg_core_ttypes_hpp
   2 #define libjmmcg_core_ttypes_hpp
   3 
   4 /******************************************************************************
   5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/ttypes.hpp 2220 2017-11-07 22:42:35Z jmmcg $
   6 **
   7 ** Copyright (C) 2002 by J.M.McGuiness, coder@hussar.me.uk
   8 **
   9 ** This library is free software; you can redistribute it and/or
  10 ** modify it under the terms of the GNU Lesser General Public
  11 ** License as published by the Free Software Foundation; either
  12 ** version 2.1 of the License, or (at your option) any later version.
  13 **
  14 ** This library is distributed in the hope that it will be useful,
  15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17 ** Lesser General Public License for more details.
  18 **
  19 ** You should have received a copy of the GNU Lesser General Public
  20 ** License along with this library; if not, write to the Free Software
  21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23 
  24 #include "debug_defines.hpp"
  25 
  26 #include <cassert>
  27 #include <cinttypes>
  28 #include <cmath>
  29 
  30 #ifdef _MSC_VER
  31 
  32 #       include <tchar.h>
  33 
  34 #endif  //      _MSC_VER
  35 
  36 #include <algorithm>
  37 #include <functional>
  38 #include <istream>
  39 #include <iterator>
  40 #include <ostream>
  41 #include <sstream>
  42 #include <string>
  43 
  44 #ifndef _TCHAR_DEFINED
  45 #       define TCHAR jmmcg::tchar;
  46 #       define _TCHAR_DEFINED
  47 #       ifdef UNICODE
  48 #               define _JMMCG_WIDE_CHARS
  49 #       endif
  50 #endif
  51 
  52 #undef _T
  53 
  54 namespace jmmcg {
  55 
  56 // Macros to make easy work of making your code wide-char compliant.
  57 #ifdef _JMMCG_WIDE_CHARS
  58         typedef std::wchar_t tchar;
  59 #       define _T(str) L##str
  60 #       define tsscanf swscanf
  61 #       define tstrlen wstrlen
  62 #else
  63         typedef char tchar;
  64 #       define _T(str) str
  65 #       define tsscanf sscanf
  66 #       define tstrlen strlen
  67 #endif
  68         // And to wrap some of the more used types to make them char-size independant.
  69         typedef std::basic_string<tchar> tstring;
  70         typedef std::basic_stringstream<tchar> tstringstream;
  71         typedef std::basic_istringstream<tchar> tistringstream;
  72         typedef std::basic_ostringstream<tchar> tostringstream;
  73         typedef std::basic_istream<tchar> tistream;
  74         typedef std::basic_ostream<tchar> tostream;
  75 
  76 #if defined(_MSC_VER) && (_MSC_VER < 1300)
  77 
  78         /**
  79                 \todo Implement using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
  80         */
  81         inline tostream & __fastcall
  82         operator<<(tostream &o,const __int64 &i) {
  83                 tchar buff[34];
  84                 int radix=10;
  85                 if ((o.flags() & std::ios::basefield) == std::ios::oct) {
  86                         radix=8;
  87                 } else if ((o.flags() & std::ios::basefield) == std::ios::hex) {
  88                         radix=16;
  89                 }
  90                 ::_i64tot_s(i, buff, sizeof(buff), radix);
  91                 o << buff;
  92                 return o;
  93         }
  94 
  95         /**
  96                 \todo Implement using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
  97         */
  98         inline tistream & __fastcall
  99         operator>>(tistream &o,__int64 &i) {
 100                 tstring buff;
 101                 o>>buff;
 102                 i=::_ttoi64(buff.c_str());
 103                 return o;
 104         }
 105 
 106         /**
 107                 \todo Implement using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
 108         */
 109         inline tostream &  __fastcall
 110         operator<<(tostream &o,const unsigned __int64 &i) {
 111                 tchar buff[34];
 112                 int radix=10;
 113                 if ((o.flags() & std::ios::basefield) == std::ios::oct) {
 114                         radix=8;
 115                 } else if ((o.flags() & std::ios::basefield) == std::ios::hex) {
 116                         radix=16;
 117                 }
 118                 ::_ui64tot_s(i, buff, sizeof(buff), radix);
 119                 o << buff;
 120                 return o;
 121         }
 122 
 123         /**
 124                 \todo Implement using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
 125         */
 126         inline tistream & __fastcall
 127         operator>>(tistream &o,unsigned __int64 &i) {
 128                 tstring buff;
 129                 o>>buff;
 130                 i=::_ttoi64(buff.c_str());
 131                 return o;
 132         }
 133 
 134 #endif  // _MSC_VER
 135 
 136         /// Returns the number of digits in the base 10 representation of an uint64_t.
 137         /**
 138                 Useful for preallocating buffers and such. It is also used internally, see below. Measurements suggest that defining a separate overload for 32-bit integers is not worthwhile.
 139 
 140                 From <a href="https://github.com/facebook/folly">Folly</a>.
 141         */
 142         constexpr inline std::uint32_t
 143         num_digits_in_base10(std::uint64_t v) noexcept(true) __attribute__((pure));
 144         constexpr inline std::uint32_t
 145         num_digits_in_base10(std::uint64_t v) noexcept(true) {
 146 #ifdef __x86_64__
 147                 // For this arch we can get a little help from specialized CPU instructions which can count leading zeroes; 64 minus that is appx. log (base 2).  Use that to approximate base-10 digits (log_10) and then adjust if needed.
 148 
 149                 // 10^i, defined for i:[0, ..., 19).  This is 20*8==160 bytes, which fits neatly into 5 cache lines (assuming a cache line size of 64).
 150                 ALIGN_TO_L1_CACHE constexpr const std::uint64_t powersOf10[]={
 151                         1ULL,
 152                         10ULL,
 153                         100ULL,
 154                         1000ULL,
 155                         10000ULL,
 156                         100000ULL,
 157                         1000000ULL,
 158                         10000000ULL,
 159                         100000000ULL,
 160                         1000000000ULL,
 161                         10000000000ULL,
 162                         100000000000ULL,
 163                         1000000000000ULL,
 164                         10000000000000ULL,
 165                         100000000000000ULL,
 166                         1000000000000000ULL,
 167                         10000000000000000ULL,
 168                         100000000000000000ULL,
 169                         1000000000000000000ULL,
 170                         10000000000000000000ULL,
 171                 };
 172 
 173                 // "count leading zeroes" operation not valid; for 0; special case this.
 174                 if (UNLIKELY(!v)) {
 175                         return 1;
 176                 }
 177                 // Bits is in the ballpark of log_2(v).
 178                 const std::uint8_t leadingZeroes=__builtin_clzll(v);
 179                 const auto bits=sizeof(std::uint64_t)*8-1-leadingZeroes;
 180 
 181                 // Approximate log_10(v) == log_10(2) * bits.
 182                 // Integer magic below: 77/256 is appx. 0.3010 (log_10(2)).
 183                 // The +1 is to make this the ceiling of the log_10 estimate.
 184                 const std::uint32_t minLength=1+((bits*77)>>8);
 185 
 186                 // Return that log_10 lower bound, plus adjust if input >= 10^(that bound)
 187                 // in case there's a small error and we misjudged length.
 188                 return minLength+static_cast<std::uint32_t>(UNLIKELY(v>=powersOf10[minLength]));
 189 #else
 190                 std::uint32_t result=1;
 191                 for (;;) {
 192                         if (LIKELY(v<10)) return result;
 193                         if (LIKELY(v<100)) return result + 1;
 194                         if (LIKELY(v<1000)) return result + 2;
 195                         if (LIKELY(v<10000)) return result + 3;
 196                         // Skip ahead by 4 orders of magnitude
 197                         v/=10000U;
 198                         result+=4;
 199                 }
 200 #endif
 201         }
 202 
 203         /// Copies the ASCII base 10 representation of v into the buffer and returns the number of bytes written.
 204         /**
 205                 Assumes the buffer points to num_digits_in_base10(v) bytes of valid memory. Note that uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes, uint16_t needs at most 5 bytes, and so on. Measurements suggest that defining a separate overload for 32-bit integers is not worthwhile.
 206 
 207                 This primitive is unsafe because it makes the size assumption and does not write the terminal '\0'.
 208 
 209                 From <a href="https://github.com/facebook/folly">Folly</a>.
 210         */
 211         inline std::uint32_t
 212         uint64ToBufferUnsafe(std::uint64_t v, char * const buffer, __attribute__((unused)) std::uint32_t sz) noexcept(true) __attribute__((pure));
 213         inline std::uint32_t
 214         uint64ToBufferUnsafe(std::uint64_t v, char * const buffer, __attribute__((unused)) std::uint32_t sz) noexcept(true) {
 215                 assert(sz>0);
 216                 auto const digits_to_write=num_digits_in_base10(v);
 217                 assert(digits_to_write<=sz);
 218                 // WARNING: using size_t or pointer arithmetic for pos slows down the loop below 20x. This is because several 32-bit ops can be done in parallel, but only fewer 64-bit ones.
 219                 std::uint32_t pos=digits_to_write-1;
 220                 while (v>=10) {
 221                         // Keep these together so a peephole optimization "sees" them and computes them in one shot.
 222                         const auto q=v/10;
 223                         const auto r=static_cast<std::uint32_t>(v%10);
 224                         buffer[pos--]='0'+r;
 225                         v=q;
 226                 }
 227                 assert(pos==0);
 228                 // Last digit is trivial to handle.
 229                 buffer[pos]='0'+static_cast<char>(v);
 230                 return digits_to_write;
 231         }
 232 
 233         /// Returns the ASCII base 10 representation in the buffer.
 234         /**
 235                 \param buffer   The ACSII base 10 representation of the natural number.
 236                 \param sz       The length of the buffer.
 237 
 238                 From <a href="https://github.com/facebook/folly">Folly</a>.
 239         */
 240         inline std::uint32_t
 241         folly_ascii_to_int(char const *buffer, std::uint32_t sz) noexcept(true) __attribute__((pure));
 242         inline std::uint32_t
 243         folly_ascii_to_int(char const *buffer, std::uint32_t sz) noexcept(true) {
 244                 assert(buffer);
 245                 assert(sz>0);
 246                 ALIGN_TO_L1_CACHE static constexpr const std::uint64_t pow10[]={
 247                         10000000000000000000ULL,
 248                         1000000000000000000ULL,
 249                         100000000000000000ULL,
 250                         10000000000000000ULL,
 251                         1000000000000000ULL,
 252                         100000000000000ULL,
 253                         10000000000000ULL,
 254                         1000000000000ULL,
 255                         100000000000ULL,
 256                         10000000000ULL,
 257                         1000000000ULL,
 258                         100000000ULL,
 259                         10000000ULL,
 260                         1000000ULL,
 261                         100000ULL,
 262                         10000ULL,
 263                         1000ULL,
 264                         100ULL,
 265                         10ULL,
 266                         1ULL
 267                 };
 268                 char const * const e=buffer+sz;
 269                 std::uint32_t result=0;
 270                 auto i=sizeof(pow10)/sizeof(pow10[0])-sz;
 271                 for(; buffer!=e; ++buffer) {
 272                         assert(std::isdigit(*buffer));
 273                         const std::uint32_t digit=std::uint32_t(*buffer)-'0';
 274                         assert(digit<10U);
 275                         result+=digit*pow10[i++];
 276                 }
 277                 assert(std::strtol(e-sz, nullptr, 10)==result);
 278                 return result;
 279         }
 280 
 281         /// Returns the ASCII base 10 representation in the buffer.
 282         /**
 283                 \param buffer   The ACSII base 10 representation of the natural number.
 284                 \param sz       The length of the buffer.
 285         */
 286         template<unsigned Base> inline std::uint32_t
 287         ascii_to_int_baseline(char const * const buffer, std::size_t sz) noexcept(true) __attribute__((pure));
 288         template<unsigned Base> inline std::uint32_t
 289         ascii_to_int_baseline(char const * const buffer, std::size_t sz) noexcept(true) {
 290                 assert(buffer);
 291                 assert(sz>0);
 292                 char const *digit=buffer+sz;
 293                 std::uint32_t result=0;
 294                 std::uint32_t units=1;
 295                 while (--digit!=buffer) {
 296                         assert(std::isdigit(*digit));
 297                         const std::uint32_t d=std::uint32_t(*digit)-'0';
 298                         assert(d<10U);
 299                         result+=d*units;
 300                         units*=Base;
 301                 }
 302                 assert(std::isdigit(*digit));
 303                 result+=((*digit)-'0')*units;
 304                 assert(std::strtol(buffer, nullptr, Base)==result);
 305                 return result;
 306         }
 307 
 308         // Function to convert anything to a tstring, as long as "operator<<(...)" is defined for it.
 309         template<typename T> inline tstring __fastcall
 310         tostring(const T &val) {
 311                 tostringstream ss;
 312                 ss<<val;
 313                 return ss.str();
 314         }
 315         template<> inline tstring __fastcall
 316         tostring<tstring>(const tstring &val) {
 317                 return val;
 318         }
 319 
 320         template<typename A,typename Fmt> inline tstring __fastcall
 321         tostring(const A &a,const Fmt &format) {
 322                 tostringstream ss;
 323                 ss<<format<<a;
 324                 return ss.str();
 325         }
 326 
 327         /// Convert the input value to a string stored in the supplied buffer.
 328         /**
 329                 \param v        The integer, decimal input value.
 330                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 331                 \param  Sz      The size of the input buffer.
 332         */
 333         template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 334         tostring(std::uint64_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
 335         template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 336         tostring(std::uint64_t v, char (&buff)[Sz]) noexcept(true) {
 337                 return uint64ToBufferUnsafe(v, buff, Sz);
 338         }
 339         /// Convert the input value to a string stored in the supplied buffer.
 340         /**
 341                 \param v        The integer, decimal input value.
 342                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted, zero-padded, right-justified.
 343                 \param  Sz      The size of the input buffer.
 344         */
 345         template<std::uint8_t Base, std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 346         tostring_zero_pad_right_justify(std::uint32_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
 347         template<std::uint8_t Base, std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 348         tostring_zero_pad_right_justify(std::uint32_t v, char (&buff)[Sz]) noexcept(true) {
 349                 for (std::size_t i=Sz; i; --i) {
 350                         auto const q=v/Base;
 351                         auto const r=static_cast<char>(v%Base);
 352                         buff[i-1]=static_cast<char>(static_cast<std::uint8_t>('0')+r);
 353                         v=q;
 354                 }
 355                 return Sz;
 356         }
 357         /// Convert the input value to a string stored in the supplied buffer.
 358         /**
 359                 \param v        The integer, decimal input value.
 360                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 361                 \param  Sz      The size of the input buffer.
 362         */
 363         template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 364         tostring(std::int64_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
 365         template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
 366         tostring(std::int64_t v, char (&buff)[Sz]) noexcept(true) {
 367                 if (v<0) {
 368                         buff[0]='-';
 369                         return uint64ToBufferUnsafe(-v, buff+1, Sz-1);
 370                 } else {
 371                         return uint64ToBufferUnsafe(v, buff, Sz);
 372                 }
 373         }
 374         template<class V> inline std::size_t
 375         tostring(V v, char * const buff, std::size_t sz) noexcept(true)=delete;
 376         /// Convert the input value to a string stored in the supplied buffer.
 377         /**
 378                 \param v        The integer, decimal input value.
 379                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 380                 \param  sz      The size of the input buffer.
 381         */
 382         template<> inline std::size_t
 383         tostring<int>(int v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 384         template<> inline std::size_t
 385         tostring<int>(int v, char * const buff, std::size_t sz) noexcept(true) {
 386                 if (v<0) {
 387                         buff[0]='-';
 388                         return uint64ToBufferUnsafe(-v, buff+1, sz-1);
 389                 } else {
 390                         return uint64ToBufferUnsafe(v, buff, sz);
 391                 }
 392         }
 393         /// Convert the input value to a string stored in the supplied buffer.
 394         /**
 395                 \param v        The integer, decimal input value.
 396                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 397                 \param  sz      The size of the input buffer.
 398         */
 399         template<> inline std::size_t
 400         tostring<long>(long v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 401         template<> inline std::size_t
 402         tostring<long>(long v, char * const buff, std::size_t sz) noexcept(true) {
 403                 if (v<0) {
 404                         buff[0]='-';
 405                         return uint64ToBufferUnsafe(-v, buff+1, sz-1);
 406                 } else {
 407                         return uint64ToBufferUnsafe(v, buff, sz);
 408                 }
 409         }
 410         /// Convert the input value to a string stored in the supplied buffer.
 411         /**
 412                 \param v        The integer, decimal input value.
 413                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 414                 \param  sz      The size of the input buffer.
 415         */
 416         template<> inline std::size_t
 417         tostring<std::size_t>(std::size_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 418         template<> inline std::size_t
 419         tostring<std::size_t>(std::size_t v, char * const buff, std::size_t sz) noexcept(true) {
 420                 return uint64ToBufferUnsafe(v, buff, sz);
 421         }
 422         /// Convert the input value to a string stored in the supplied buffer.
 423         /**
 424                 \param v        The integer, decimal input value.
 425                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 426                 \param  sz      The size of the input buffer.
 427         */
 428         inline std::size_t
 429         tostring(std::uint32_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 430         inline std::size_t
 431         tostring(std::uint32_t v, char * const buff, std::size_t sz) noexcept(true) {
 432                 return uint64ToBufferUnsafe(v, buff, sz);
 433         }
 434         /// Convert the input value to a string stored in the supplied buffer.
 435         /**
 436                 \param v        The integer, decimal input value.
 437                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 438                 \param  sz      The size of the input buffer.
 439         */
 440         inline std::size_t
 441         tostring(std::int64_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 442         inline std::size_t
 443         tostring(std::int64_t v, char * const buff, std::size_t sz) noexcept(true) {
 444                 if (v<0) {
 445                         buff[0]='-';
 446                         return uint64ToBufferUnsafe(-v, buff+1, sz-1);
 447                 } else {
 448                         return uint64ToBufferUnsafe(v, buff, sz);
 449                 }
 450         }
 451         /// Convert the input value to a string stored in the supplied buffer.
 452         /**
 453                 \param v        The integer, decimal input value.
 454                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal integers shall be converted.
 455                 \param  sz      The size of the input buffer.
 456         */
 457         inline std::size_t
 458         tostring(std::uint64_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
 459         inline std::size_t
 460         tostring(std::uint64_t v, char * const buff, std::size_t sz) noexcept(true) {
 461                 return uint64ToBufferUnsafe(v, buff, sz);
 462         }
 463         /// Convert the input value to a string stored in the supplied buffer.
 464         /**
 465                 \param v        The floating-point, decimal input value.
 466                 \param  buff    A buffer that must be large enough into which the value, represented as ASCII, decimal, floating-point number shall be converted.
 467                 \param  sz      The size of the input buffer.
 468 
 469                 \todo This is pretty slow. Write an optimised version for just decimal conversion.
 470         */
 471         inline std::size_t
 472         tostring(double v, char * const buff, std::size_t sz) noexcept(true) {
 473                 return std::snprintf(buff, sz, "%f", v);
 474         }
 475 
 476         // Function to convert anything from a tstring, as long as "operator>>(...)" is defined for it.
 477         template<typename T> inline void __fastcall
 478         fromstring(const tstring &str, T &val) {
 479                 tstringstream ss;
 480                 ss<<str;
 481                 ss>>val;
 482         }
 483         template<> inline void __fastcall
 484         fromstring<tstring>(const tstring &str, tstring &val) {
 485                 val=str;
 486         }
 487         template<class V> typename std::enable_if<std::is_integral<V>::value || std::is_floating_point<V>::value, V>::type
 488         fromstring(char const * const, std::uint32_t) noexcept(true) __attribute__((pure)) =delete;
 489         /// Convert the decimal value contained in the input string into an integral value.
 490         /**
 491                 \param  buff    The input buffer that must contain the decimal value only.
 492                 \return The scanned value.
 493         */
 494         template<> inline long
 495         fromstring<long>(char const * const begin, std::uint32_t sz) noexcept(true) __attribute__((pure));
 496         template<> inline long
 497         fromstring<long>(char const * const begin, std::uint32_t sz) noexcept(true) {
 498                 return ascii_to_int_baseline<10u>(begin, sz);
 499         }
 500         /// Convert the decimal value contained in the input string into an integral value.
 501         /**
 502                 \param  buff    The input buffer that must contain the decimal value only.
 503                 \return The scanned value.
 504         */
 505         template<> inline unsigned long
 506         fromstring<unsigned long>(char const * const begin, std::uint32_t sz) noexcept(true) __attribute__((pure));
 507         template<> inline unsigned long
 508         fromstring<unsigned long>(char const * const begin, std::uint32_t sz) noexcept(true) {
 509                 return ascii_to_int_baseline<10u>(begin, sz);
 510         }
 511         /// Convert the decimal value contained in the input string into an integral value.
 512         /**
 513                 \param  buff    The input buffer that must contain the decimal value only.
 514                 \return The scanned value.
 515         */
 516         template<> inline double
 517         fromstring<double>(char const * const begin, std::uint32_t) noexcept(true) __attribute__((pure));
 518         template<> inline double
 519         fromstring<double>(char const * const begin, std::uint32_t) noexcept(true) {
 520                 constexpr unsigned Base=10;
 521                 char const *decimal_point=begin;
 522                 while (*decimal_point!='.') {
 523                         ++decimal_point;
 524                 }
 525                 char const *whole=decimal_point;
 526                 double result=0;
 527                 unsigned units=0;
 528                 char const *fraction=decimal_point+1;
 529                 while (std::isdigit(*fraction)) {
 530                         ++fraction;
 531                         ++units;
 532                 }
 533                 while (--fraction!=decimal_point) {
 534                         assert(std::isdigit(*fraction));
 535                         result+=((*fraction)-'0')/__builtin_powif(Base, units);
 536                         --units;
 537                 }
 538                 units=1;
 539                 while (--whole!=begin) {
 540                         assert(std::isdigit(*whole));
 541                         result+=((*whole)-'0')*units;
 542                         units*=Base;
 543                 }
 544                 assert(std::isdigit(*whole));
 545                 result+=((*whole)-'0')*units;
 546                 assert(std::abs(std::strtod(begin, nullptr)-result)<0.000001d);
 547                 return result;
 548         }
 549 
 550         template<typename T> inline void  __fastcall
 551         delete_ptr(T *ptr) {
 552                 // T should be a pointer type really....
 553                 delete ptr;
 554         }
 555 
 556         /// A simple class to turn a character into upper case according to the current locale settings.
 557         template<typename T>
 558         class upperletter : public std::unary_function<T, T> {
 559         public:
 560                 upperletter()
 561                 : ct(std::use_facet<std::ctype<T> >(std::locale())) {
 562                 }
 563                 T operator()(const T c) const {
 564                         return ct.toupper(c);
 565                 }
 566 
 567         private:
 568                 std::ctype<T> const &ct;
 569         };
 570 
 571         /// A simple class to turn a character into lowercase according to the current locale settings.
 572         template<typename T>
 573         class lowerletter : public std::unary_function<T, T> {
 574         public:
 575                 lowerletter()
 576                 : ct(std::use_facet<std::ctype<T> >(std::locale())) {
 577                 }
 578 
 579                 T operator()(const T c) const {
 580                         return ct.tolower(c);
 581                 }
 582 
 583         private:
 584                 std::ctype<T> const &ct;
 585         };
 586 
 587         /// Turn the input string into an uppercase variant according to the current locale settings.
 588         inline tstring
 589         toupper(const tstring &l) {
 590                 tstring u;
 591                 std::transform(l.begin(),l.end(),std::back_inserter(u),upperletter<tstring::value_type>());
 592                 return u;
 593         }
 594 
 595         /// Turn the input string into a lowercase variant according to the current locale settings.
 596         inline tstring
 597         tolower(const tstring &u) {
 598                 tstring l;
 599                 std::transform(u.begin(),u.end(),std::back_inserter<tstring>(l),lowerletter<tstring::value_type>());
 600                 return l;
 601         }
 602 
 603         /// Turn the input range into an uppercase variant according to the current locale settings.
 604         template<class Iter> inline Iter
 605         toupper(const Iter b,const Iter e,Iter o) {
 606                 std::transform(b,e,o,upperletter<typename std::iterator_traits<Iter>::value_type>());
 607                 return o;
 608         }
 609 
 610         /// Turn the input range into a lowercase variant according to the current locale settings.
 611         template<class Iter> inline Iter
 612         tolower(const Iter b,const Iter e,Iter o) {
 613                 std::transform(b,e,o,lowerletter<typename std::iterator_traits<Iter>::value_type>());
 614                 return o;
 615         }
 616 
 617 }
 618 
 619 namespace std {
 620 
 621         inline std::ostream & __fastcall
 622         operator<<(std::ostream &o, std::exception_ptr ex) noexcept(false) {
 623                 try {
 624                         if (ex) {
 625                                 std::rethrow_exception(ex);
 626                         }
 627                 } catch (std::exception const &e) {
 628                         o<<e.what();
 629                 }
 630                 return o;
 631         }
 632 
 633 }
 634 
 635 #endif

/* [<][>][^][v][top][bottom][index][help] */