1 #ifndef LIBJMMCG_CORE_TTYPES_HPP
2 #define LIBJMMCG_CORE_TTYPES_HPP
43 #ifndef _TCHAR_DEFINED
45 # define _TCHAR_DEFINED
47 # define _JMMCG_WIDE_CHARS
56 #ifdef _JMMCG_WIDE_CHARS
58 # define _T(str) L##str
59 # define tsscanf swscanf
60 # define tstrlen wstrlen
64 # define tsscanf sscanf
65 # define tstrlen strlen
75 #if defined(_MSC_VER) && (_MSC_VER < 1300
)
141 constexpr inline std::uint32_t
143 constexpr inline std::uint32_t
166 10000000000000000ULL,
167 100000000000000000ULL,
168 1000000000000000000ULL,
169 10000000000000000000ULL,
177 const std::uint8_t leadingZeroes=__builtin_clzll(v);
178 const auto bits=
sizeof(
std::uint64_t)*8-1-leadingZeroes;
183 const std::uint32_t minLength=1+((bits*77)>>8);
187 return minLength+
static_cast<
std::uint32_t>(
UNLIKELY(v>=powersOf10[minLength]));
189 std::uint32_t result=1;
191 if (LIKELY(v<10))
return result;
192 if (LIKELY(v<100))
return result + 1;
193 if (LIKELY(v<1000))
return result + 2;
194 if (LIKELY(v<10000))
return result + 3;
216 assert(digits_to_write<=sz);
218 std::uint32_t pos=digits_to_write-1;
222 const auto r=
static_cast<
std::uint32_t>(v%10);
228 buffer[pos]=
'0'+
static_cast<
char>(v);
229 return digits_to_write;
246 10000000000000000000ULL,
247 1000000000000000000ULL,
248 100000000000000000ULL,
249 10000000000000000ULL,
267 char const *
const e=buffer+sz;
268 std::uint64_t result=0;
269 auto i=
sizeof(pow10)/
sizeof(pow10[0])-sz;
270 for(; buffer!=e; ++buffer) {
271 assert(std::isdigit(*buffer));
272 const std::uint32_t digit=
std::uint32_t(*buffer)-
'0';
274 result+=digit*pow10[i++];
276 assert(std::strtoull(e-sz,
nullptr, 10)==result);
285 template<
unsigned Base>
inline std::uint64_t
287 template<
unsigned Base>
inline std::uint64_t
291 char const *digit=buffer+sz;
292 std::uint64_t result=0;
293 std::uint64_t units=1;
294 while (--digit!=buffer) {
295 assert(std::isdigit(*digit));
296 const std::uint32_t d=
std::uint32_t(*digit)-
'0';
301 assert(std::isdigit(*digit));
302 result+=((*digit)-
'0')*units;
303 assert(std::strtoull(buffer,
nullptr, Base)==result);
308 template<
typename T>
inline tstring __fastcall
314 template<
std::size_t N>
inline tstring __fastcall
315 tostring(
const std::array<tstring::value_type, N> &val) {
317 if (std::find(val.begin(), val.end(),
_T(
'\0'))!=val.end()) {
320 std::copy(val.begin(), val.end(), std::ostream_iterator<tstring::value_type>(ss));
325 tostring<tstring>(
const tstring &val) {
329 template<
typename A,
typename Fmt>
inline tstring __fastcall
343 tostring(
std::uint64_t v,
char (&buff)[Sz])
noexcept(
true)
__attribute__((pure));
346 return uint64ToBufferUnsafe(v, buff, Sz);
358 for (
std::size_t i=Sz; i; --i) {
360 auto const r=
static_cast<
char>(v%Base);
361 buff[i-1]=
static_cast<
char>(
static_cast<
std::uint8_t>(
'0')+r);
373 tostring(
std::int64_t v,
char (&buff)[Sz])
noexcept(
true)
__attribute__((pure));
378 return uint64ToBufferUnsafe(-v, buff+1, Sz-1);
380 return uint64ToBufferUnsafe(v, buff, Sz);
383 template<
class V>
inline std::size_t
384 tostring(V v,
char *
const buff,
std::size_t sz)
noexcept(
true)=
delete;
391 template<>
inline std::size_t
392 tostring<
int>(
int v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
393 template<>
inline std::size_t
394 tostring<
int>(
int v,
char *
const buff,
std::size_t sz)
noexcept(
true) {
408 template<>
inline std::size_t
409 tostring<
unsigned int>(
unsigned int v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
410 template<>
inline std::size_t
411 tostring<
unsigned int>(
unsigned int v,
char *
const buff,
std::size_t sz)
noexcept(
true) {
420 template<>
inline std::size_t
421 tostring<
long>(
long v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
422 template<>
inline std::size_t
423 tostring<
long>(
long v,
char *
const buff,
std::size_t sz)
noexcept(
true) {
437 template<>
inline std::size_t
438 tostring<
unsigned long>(
unsigned long v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
439 template<>
inline std::size_t
440 tostring<
unsigned long>(
unsigned long v,
char *
const buff,
std::size_t sz)
noexcept(
true) {
450 tostring(
std::uint32_t v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
462 tostring(
std::int64_t v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
479 tostring(
std::uint64_t v,
char *
const buff,
std::size_t sz)
noexcept(
true)
__attribute__((pure));
493 tostring(
double v,
char *
const buff,
std::size_t sz)
noexcept(
true) {
494 return std::snprintf(buff, sz,
"%f", v);
498 template<
typename T>
inline void __fastcall
504 template<>
inline void __fastcall
508 template<
class V>
typename std::enable_if<
std::is_integral<V>::value ||
std::is_floating_point<V>::value, V>::
type
509 fromstring(
char const *
const,
std::uint32_t)
noexcept(
true)
__attribute__((pure)) =
delete;
515 template<>
inline int
516 fromstring<
int>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
517 template<>
inline int
518 fromstring<
int>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
519 return ascii_to_int_baseline<10u>(begin, sz);
526 template<>
inline unsigned int
527 fromstring<
unsigned int>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
528 template<>
inline unsigned int
529 fromstring<
unsigned int>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
530 return ascii_to_int_baseline<10u>(begin, sz);
537 template<>
inline long
538 fromstring<
long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
539 template<>
inline long
540 fromstring<
long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
541 return ascii_to_int_baseline<10u>(begin, sz);
548 template<>
inline unsigned long
549 fromstring<
unsigned long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
550 template<>
inline unsigned long
551 fromstring<
unsigned long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
552 return ascii_to_int_baseline<10u>(begin, sz);
559 template<>
inline long long
560 fromstring<
long long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
561 template<>
inline long long
562 fromstring<
long long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
563 return ascii_to_int_baseline<10u>(begin, sz);
570 template<>
inline unsigned long long
571 fromstring<
unsigned long long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true)
__attribute__((pure));
572 template<>
inline unsigned long long
573 fromstring<
unsigned long long>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
574 return ascii_to_int_baseline<10u>(begin, sz);
581 template<>
inline double
582 fromstring<
double>(
char const *
const begin,
std::uint32_t)
noexcept(
true)
__attribute__((pure));
583 template<>
inline double
584 fromstring<
double>(
char const *
const begin,
std::uint32_t sz)
noexcept(
true) {
585 constexpr unsigned Base=10;
586 char const *decimal_point=begin;
587 using diff_t=
decltype(std::distance(begin, decimal_point));
588 static_assert(std::numeric_limits<std::uint32_t>::max()<=std::numeric_limits<diff_t>::max());
589 while (
std::distance(begin, decimal_point)<
static_cast<diff_t>(sz) && *decimal_point!=
'.') {
592 char const *whole=decimal_point;
595 if (
std::distance(begin, decimal_point)<
static_cast<diff_t>(sz)) {
596 const std::size_t num_frac_digits=sz-(decimal_point-begin);
597 char const *fraction=decimal_point+num_frac_digits;
598 units=num_frac_digits;
599 while (--fraction!=decimal_point) {
600 assert(std::isdigit(*fraction));
602 result+=((*fraction)-
'0')/__builtin_powi(Base, units);
606 while (--whole!=begin) {
607 assert(std::isdigit(*whole));
608 result+=((*whole)-
'0')*units;
611 assert(std::isdigit(*whole));
612 result+=((*whole)-
'0')*units;
613 assert(std::abs(std::strtod(begin,
nullptr)-result)<0.000001);
617 template<
typename T>
inline void __fastcall
628 : ct(
std::use_facet<
std::ctype<T> >(
std::locale())) {
631 return ct.toupper(c);
635 std::ctype<T>
const &ct;
643 : ct(
std::use_facet<
std::ctype<T> >(
std::locale())) {
647 return ct.tolower(c);
651 std::ctype<T>
const &ct;
658 std::transform(l.begin(),l.end(),std::back_inserter(u),upperletter<tstring::value_type>());
666 std::transform(u.begin(),u.end(),std::back_inserter<tstring>(l),lowerletter<tstring::value_type>());
671 template<
class Iter>
inline Iter
673 std::transform(b,e,o,
upperletter<
typename std::iterator_traits<Iter>::value_type>());
678 template<
class Iter>
inline Iter
680 std::transform(b,e,o,
lowerletter<
typename std::iterator_traits<Iter>::value_type>());
690 if (std::find(val.begin(), val.end(),
_T(
'\0'))!=val.end()) {
693 o.write(val.data(), Sz);
698 inline std::ostream &
__fastcall
699 operator<<(
std::ostream &o,
std::exception_ptr ex)
noexcept(
false) {
702 std::rethrow_exception(ex);
704 }
catch (
std::exception
const &e) {