1/** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef LIBPANDABASE_UTILS_STRING_HELPERS_H 17#define LIBPANDABASE_UTILS_STRING_HELPERS_H 18 19#include <securec.h> 20 21#include <cstdarg> 22 23#include <algorithm> 24#include <array> 25#include <string> 26#include <cerrno> 27#include <cstdlib> 28#include <limits> 29#include <type_traits> 30 31namespace panda::helpers::string { 32 33inline std::string Vformat(const char *fmt, va_list args) 34{ 35 static constexpr size_t SIZE = 1024; 36 37 std::string result; 38 result.resize(SIZE); 39 40 bool is_truncated = true; 41 while (is_truncated) { 42 va_list copy_args; 43 va_copy(copy_args, args); 44 int r = vsnprintf_truncated_s(result.data(), result.size() + 1, fmt, copy_args); 45 va_end(copy_args); 46 47 if (r < 0) { 48 return ""; 49 } 50 51 is_truncated = static_cast<size_t>(r) == result.size(); 52 result.resize(result.size() * 2U); 53 } 54 55 result.erase(std::find(result.begin(), result.end(), '\0'), result.end()); 56 57 return result; 58} 59 60// NOLINTNEXTLINE(cert-dcl50-cpp) 61inline std::string Format(const char *fmt, ...) 62{ 63 va_list args; 64 va_start(args, fmt); // NOLINT(cppcoreguidelines-pro-type-vararg) 65 66 std::string result = Vformat(fmt, args); 67 68 va_end(args); 69 return result; 70} 71 72template <typename T> 73bool ParseInt(const char *str, T *num, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) 74{ 75 static_assert(std::is_signed<T>::value, "it can't parse unsigned types"); 76 while (isspace(*str)) { 77 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 78 str++; 79 } 80 81 constexpr size_t BASE16 = 16; 82 constexpr size_t BASE10 = 10; 83 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 84 int base = (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) ? BASE16 : BASE10; 85 errno = 0; 86 char *end = nullptr; 87 // NOLINTNEXTLINE(google-runtime-int) 88 long long int result = strtoll(str, &end, base); 89 if (str == end || *end != '\0') { 90 errno = EINVAL; 91 return false; 92 } 93 if (result < min || max < result) { 94 errno = ERANGE; 95 return false; 96 } 97 if (num != nullptr) { 98 *num = static_cast<T>(result); 99 } 100 return true; 101} 102 103template <typename T> 104bool ParseInt(const std::string &str, T *num, T min = std::numeric_limits<T>::min(), 105 T max = std::numeric_limits<T>::max()) 106{ 107 return ParseInt(str.c_str(), num, min, max); 108} 109 110} // namespace panda::helpers::string 111 112#endif // LIBPANDABASE_UTILS_STRING_HELPERS_H 113