91 lines · c
1//===-- Definition of a class for mbstate_t and conversion -----*-- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H10#define LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H11 12#include "hdr/types/char32_t.h"13#include "hdr/types/char8_t.h"14#include "hdr/types/size_t.h"15#include "src/__support/CPP/type_traits.h"16#include "src/__support/common.h"17#include "src/__support/error_or.h"18#include "src/__support/wchar/character_converter.h"19#include "src/__support/wchar/mbstate.h"20 21namespace LIBC_NAMESPACE_DECL {22namespace internal {23 24template <typename T> class StringConverter {25private:26 CharacterConverter cr;27 const T *src;28 size_t src_len;29 size_t src_idx;30 31 // # of pops we are allowed to perform (essentially size of the dest buffer)32 size_t num_to_write;33 34 ErrorOr<size_t> pushFullCharacter() {35 size_t num_pushed;36 for (num_pushed = 0; !cr.isFull() && src_idx + num_pushed < src_len;37 ++num_pushed) {38 int err = cr.push(src[src_idx + num_pushed]);39 if (err != 0)40 return Error(err);41 }42 43 // if we aren't able to read a full character from the source string44 if (src_idx + num_pushed == src_len && !cr.isFull()) {45 src_idx += num_pushed;46 return Error(-1);47 }48 49 return num_pushed;50 }51 52public:53 StringConverter(const T *s, mbstate *ps, size_t dstlen,54 size_t srclen = SIZE_MAX)55 : cr(ps), src(s), src_len(srclen), src_idx(0), num_to_write(dstlen) {}56 57 template <typename CharType> ErrorOr<CharType> pop() {58 if (num_to_write == 0)59 return Error(-1);60 61 if (cr.isEmpty() || src_idx == 0) {62 auto src_elements_read = pushFullCharacter();63 if (!src_elements_read.has_value())64 return Error(src_elements_read.error());65 66 if (cr.sizeAs<CharType>() > num_to_write) {67 cr.clear();68 return Error(-1);69 }70 71 src_idx += src_elements_read.value();72 }73 74 ErrorOr<CharType> out = cr.pop<CharType>();75 // if out isn't null terminator or an error76 if (out.has_value() && out.value() == 0)77 src_len = src_idx;78 79 num_to_write--;80 81 return out;82 }83 84 size_t getSourceIndex() { return src_idx; }85};86 87} // namespace internal88} // namespace LIBC_NAMESPACE_DECL89 90#endif // LLVM_LIBC_SRC___SUPPORT_STRING_CONVERTER_H91