• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 namespace panda::helpers::string {
32 
Vformat(const char * fmt,va_list args)33 inline 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)
Format(const char * fmt,...)61 inline 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 
72 template <typename T>
73 bool 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 
103 template <typename T>
104 bool 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