| // Copyright 2014 The PDFium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
 |  | 
 | #include "core/fxcrt/fx_extension.h" | 
 |  | 
 | #include <wchar.h> | 
 |  | 
 | #include <array> | 
 |  | 
 | #include "core/fxcrt/check.h" | 
 | #include "core/fxcrt/check_op.h" | 
 | #include "core/fxcrt/compiler_specific.h" | 
 | #include "core/fxcrt/fx_system.h" | 
 | #include "core/fxcrt/utf16.h" | 
 | #include "core/fxcrt/widestring.h" | 
 | #include "third_party/fast_float/src/include/fast_float/fast_float.h" | 
 |  | 
 | namespace { | 
 |  | 
 | time_t DefaultTimeFunction() { | 
 |   return time(nullptr); | 
 | } | 
 |  | 
 | struct tm* DefaultLocaltimeFunction(const time_t* tp) { | 
 |   return localtime(tp); | 
 | } | 
 |  | 
 | time_t (*g_time_func)() = DefaultTimeFunction; | 
 | struct tm* (*g_localtime_func)(const time_t*) = DefaultLocaltimeFunction; | 
 |  | 
 | }  // namespace | 
 |  | 
 | float FXSYS_wcstof(WideStringView pwsStr, size_t* pUsedLen) { | 
 |   // TODO(thestig): Consolidate code duplication with StringToFloatImpl(). | 
 |   // Skip leading whitespaces. | 
 |   size_t start = 0; | 
 |   size_t len = pwsStr.GetLength(); | 
 |   while (start < len && pwsStr[start] == ' ') { | 
 |     ++start; | 
 |   } | 
 |  | 
 |   // Skip a leading '+' sign. | 
 |   if (start < len && pwsStr[start] == '+') { | 
 |     ++start; | 
 |   } | 
 |  | 
 |   WideStringView sub_strc = pwsStr.Substr(start, len - start); | 
 |  | 
 |   float value; | 
 |   auto result = fast_float::from_chars(sub_strc.begin(), sub_strc.end(), value); | 
 |  | 
 |   if (pUsedLen) { | 
 |     *pUsedLen = result.ptr - pwsStr.unterminated_c_str(); | 
 |   } | 
 |  | 
 |   // Return 0 for parsing errors. Some examples of errors are an empty string | 
 |   // and a string that cannot be converted to `ReturnType`. | 
 |   return result.ec == std::errc() || result.ec == std::errc::result_out_of_range | 
 |              ? value | 
 |              : 0; | 
 | } | 
 |  | 
 | wchar_t* FXSYS_wcsncpy(wchar_t* dstStr, const wchar_t* srcStr, size_t count) { | 
 |   DCHECK(dstStr); | 
 |   DCHECK(srcStr); | 
 |   DCHECK(count > 0); | 
 |  | 
 |   // SAFETY: required from caller, enforced by UNSAFE_BUFFER_USAGE in header. | 
 |   UNSAFE_BUFFERS({ | 
 |     for (size_t i = 0; i < count; ++i) { | 
 |       dstStr[i] = srcStr[i]; | 
 |       if (dstStr[i] == L'\0') { | 
 |         break; | 
 |       } | 
 |     } | 
 |   }); | 
 |   return dstStr; | 
 | } | 
 |  | 
 | void FXSYS_IntToTwoHexChars(uint8_t n, pdfium::span<char, 2u> buf) { | 
 |   static constexpr std::array<const char, 16> kHex = { | 
 |       '0', '1', '2', '3', '4', '5', '6', '7', | 
 |       '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', | 
 |   }; | 
 |   buf[0] = kHex[n / 16]; | 
 |   buf[1] = kHex[n % 16]; | 
 | } | 
 |  | 
 | void FXSYS_IntToFourHexChars(uint16_t n, pdfium::span<char, 4u> buf) { | 
 |   FXSYS_IntToTwoHexChars(n / 256, buf.first<2u>()); | 
 |   FXSYS_IntToTwoHexChars(n % 256, buf.subspan<2u>()); | 
 | } | 
 |  | 
 | pdfium::span<const char> FXSYS_ToUTF16BE(uint32_t unicode, | 
 |                                          pdfium::span<char, 8u> buf) { | 
 |   DCHECK_LE(unicode, pdfium::kMaximumSupplementaryCodePoint); | 
 |   DCHECK(!pdfium::IsHighSurrogate(unicode)); | 
 |   DCHECK(!pdfium::IsLowSurrogate(unicode)); | 
 |  | 
 |   if (unicode <= 0xFFFF) { | 
 |     FXSYS_IntToFourHexChars(unicode, buf); | 
 |     return buf.first<4u>(); | 
 |   } | 
 |   pdfium::SurrogatePair surrogate_pair(unicode); | 
 |   FXSYS_IntToFourHexChars(surrogate_pair.high(), buf); | 
 |   FXSYS_IntToFourHexChars(surrogate_pair.low(), buf.subspan<4u>()); | 
 |   return buf; | 
 | } | 
 |  | 
 | void FXSYS_SetTimeFunction(time_t (*func)()) { | 
 |   g_time_func = func ? func : DefaultTimeFunction; | 
 | } | 
 |  | 
 | void FXSYS_SetLocaltimeFunction(struct tm* (*func)(const time_t*)) { | 
 |   g_localtime_func = func ? func : DefaultLocaltimeFunction; | 
 | } | 
 |  | 
 | time_t FXSYS_time(time_t* tloc) { | 
 |   time_t ret_val = g_time_func(); | 
 |   if (tloc) | 
 |     *tloc = ret_val; | 
 |   return ret_val; | 
 | } | 
 |  | 
 | struct tm* FXSYS_localtime(const time_t* tp) { | 
 |   return g_localtime_func(tp); | 
 | } |