//===-- Definition of a class for mbstate_t and conversion -----*-- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H #define LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H #include "hdr/types/char32_t.h" #include "hdr/types/char8_t.h" #include "hdr/types/size_t.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" #include "src/__support/error_or.h" #include "src/__support/wchar/character_converter.h" #include "src/__support/wchar/mbstate.h" namespace LIBC_NAMESPACE_DECL { namespace internal { template class StringConverter { private: CharacterConverter cr; const T *src; size_t src_len; size_t src_idx; // # of pops we are allowed to perform (essentially size of the dest buffer) size_t num_to_write; ErrorOr pushFullCharacter() { size_t num_pushed; for (num_pushed = 0; !cr.isFull() && src_idx + num_pushed < src_len; ++num_pushed) { int err = cr.push(src[src_idx + num_pushed]); if (err != 0) return Error(err); } // if we aren't able to read a full character from the source string if (src_idx + num_pushed == src_len && !cr.isFull()) { src_idx += num_pushed; return Error(-1); } return num_pushed; } public: StringConverter(const T *s, mbstate *ps, size_t dstlen, size_t srclen = SIZE_MAX) : cr(ps), src(s), src_len(srclen), src_idx(0), num_to_write(dstlen) {} template ErrorOr pop() { if (num_to_write == 0) return Error(-1); if (cr.isEmpty() || src_idx == 0) { auto src_elements_read = pushFullCharacter(); if (!src_elements_read.has_value()) return Error(src_elements_read.error()); if (cr.sizeAs() > num_to_write) { cr.clear(); return Error(-1); } src_idx += src_elements_read.value(); } ErrorOr out = cr.pop(); // if out isn't null terminator or an error if (out.has_value() && out.value() == 0) src_len = src_idx; num_to_write--; return out; } size_t getSourceIndex() { return src_idx; } }; } // namespace internal } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H