brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · 659587a Raw
112 lines · c
1//===-- Format string parser for printf -------------------------*- 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_STDIO_STRFTIME_CORE_PARSER_H10#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_PARSER_H11 12#include "core_structs.h"13#include "hdr/types/struct_tm.h"14#include "src/__support/CPP/string_view.h"15#include "src/__support/ctype_utils.h"16#include "src/__support/macros/config.h"17#include "src/__support/str_to_integer.h"18 19namespace LIBC_NAMESPACE_DECL {20namespace strftime_core {21 22class Parser {23  const char *str;24  size_t cur_pos = 0;25 26public:27  LIBC_INLINE Parser(const char *new_str) : str(new_str) {}28 29  // get_next_section will parse the format string until it has a fully30  // specified format section. This can either be a raw format section with no31  // conversion, or a format section with a conversion that has all of its32  // variables stored in the format section.33  LIBC_INLINE FormatSection get_next_section() {34    FormatSection section;35    size_t starting_pos = cur_pos;36 37    if (str[cur_pos] != '%') {38      // raw section39      section.has_conv = false;40      while (str[cur_pos] != '%' && str[cur_pos] != '\0')41        ++cur_pos;42      section.raw_string = {str + starting_pos, cur_pos - starting_pos};43      return section;44    }45 46    // format section47    section.has_conv = true;48    ++cur_pos;49 50    // flags51    section.flags = parse_flags(&cur_pos);52 53    // handle width54    section.min_width = 0;55    if (internal::isdigit(str[cur_pos])) {56      auto result = internal::strtointeger<int>(str + cur_pos, 10);57      section.min_width = result.value;58      cur_pos = cur_pos + result.parsed_len;59    }60 61    // modifiers62    switch (str[cur_pos]) {63    case ('E'):64      section.modifier = ConvModifier::E;65      ++cur_pos;66      break;67    case ('O'):68      section.modifier = ConvModifier::O;69      ++cur_pos;70      break;71    default:72      section.modifier = ConvModifier::none;73    }74 75    section.conv_name = str[cur_pos];76 77    // If the end of the format section is on the '\0'. This means we need to78    // not advance the cur_pos.79    if (str[cur_pos] != '\0')80      ++cur_pos;81 82    section.raw_string = {str + starting_pos, cur_pos - starting_pos};83    return section;84  }85 86private:87  LIBC_INLINE FormatFlags parse_flags(size_t *local_pos) {88    bool found_flag = true;89    FormatFlags flags = FormatFlags(0);90    while (found_flag) {91      switch (str[*local_pos]) {92      case '+':93        flags = static_cast<FormatFlags>(flags | FormatFlags::FORCE_SIGN);94        break;95      case '0':96        flags = static_cast<FormatFlags>(flags | FormatFlags::LEADING_ZEROES);97        break;98      default:99        found_flag = false;100      }101      if (found_flag)102        ++*local_pos;103    }104    return flags;105  }106};107 108} // namespace strftime_core109} // namespace LIBC_NAMESPACE_DECL110 111#endif // LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_PARSER_H112