xref: /aosp_15_r20/external/cpu_features/src/string_view.c (revision eca53ba6d2e951e174b64682eaf56a36b8204c89)
1*eca53ba6SRoland Levillain // Copyright 2017 Google LLC
2*eca53ba6SRoland Levillain //
3*eca53ba6SRoland Levillain // Licensed under the Apache License, Version 2.0 (the "License");
4*eca53ba6SRoland Levillain // you may not use this file except in compliance with the License.
5*eca53ba6SRoland Levillain // You may obtain a copy of the License at
6*eca53ba6SRoland Levillain //
7*eca53ba6SRoland Levillain //    http://www.apache.org/licenses/LICENSE-2.0
8*eca53ba6SRoland Levillain //
9*eca53ba6SRoland Levillain // Unless required by applicable law or agreed to in writing, software
10*eca53ba6SRoland Levillain // distributed under the License is distributed on an "AS IS" BASIS,
11*eca53ba6SRoland Levillain // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*eca53ba6SRoland Levillain // See the License for the specific language governing permissions and
13*eca53ba6SRoland Levillain // limitations under the License.
14*eca53ba6SRoland Levillain 
15*eca53ba6SRoland Levillain #include "internal/string_view.h"
16*eca53ba6SRoland Levillain 
17*eca53ba6SRoland Levillain #include <assert.h>
18*eca53ba6SRoland Levillain #include <ctype.h>
19*eca53ba6SRoland Levillain 
20*eca53ba6SRoland Levillain #include "copy.inl"
21*eca53ba6SRoland Levillain #include "equals.inl"
22*eca53ba6SRoland Levillain 
CpuFeatures_memchr(const char * const ptr,const size_t size,const char c)23*eca53ba6SRoland Levillain static const char* CpuFeatures_memchr(const char* const ptr, const size_t size,
24*eca53ba6SRoland Levillain                                       const char c) {
25*eca53ba6SRoland Levillain   for (size_t i = 0; ptr && ptr[i] != '\0' && i < size; ++i)
26*eca53ba6SRoland Levillain     if (ptr[i] == c) return ptr + i;
27*eca53ba6SRoland Levillain   return NULL;
28*eca53ba6SRoland Levillain }
29*eca53ba6SRoland Levillain 
CpuFeatures_StringView_IndexOfChar(const StringView view,char c)30*eca53ba6SRoland Levillain int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
31*eca53ba6SRoland Levillain   if (view.ptr && view.size) {
32*eca53ba6SRoland Levillain     const char* const found = CpuFeatures_memchr(view.ptr, view.size, c);
33*eca53ba6SRoland Levillain     if (found) {
34*eca53ba6SRoland Levillain       return (int)(found - view.ptr);
35*eca53ba6SRoland Levillain     }
36*eca53ba6SRoland Levillain   }
37*eca53ba6SRoland Levillain   return -1;
38*eca53ba6SRoland Levillain }
39*eca53ba6SRoland Levillain 
CpuFeatures_StringView_IndexOf(const StringView view,const StringView sub_view)40*eca53ba6SRoland Levillain int CpuFeatures_StringView_IndexOf(const StringView view,
41*eca53ba6SRoland Levillain                                    const StringView sub_view) {
42*eca53ba6SRoland Levillain   if (sub_view.size) {
43*eca53ba6SRoland Levillain     StringView remainder = view;
44*eca53ba6SRoland Levillain     while (remainder.size >= sub_view.size) {
45*eca53ba6SRoland Levillain       const int found_index =
46*eca53ba6SRoland Levillain           CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
47*eca53ba6SRoland Levillain       if (found_index < 0) break;
48*eca53ba6SRoland Levillain       remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
49*eca53ba6SRoland Levillain       if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
50*eca53ba6SRoland Levillain         return (int)(remainder.ptr - view.ptr);
51*eca53ba6SRoland Levillain       }
52*eca53ba6SRoland Levillain       remainder = CpuFeatures_StringView_PopFront(remainder, 1);
53*eca53ba6SRoland Levillain     }
54*eca53ba6SRoland Levillain   }
55*eca53ba6SRoland Levillain   return -1;
56*eca53ba6SRoland Levillain }
57*eca53ba6SRoland Levillain 
CpuFeatures_StringView_IsEquals(const StringView a,const StringView b)58*eca53ba6SRoland Levillain bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
59*eca53ba6SRoland Levillain   if (a.size == b.size) {
60*eca53ba6SRoland Levillain     return a.ptr == b.ptr || equals(a.ptr, b.ptr, b.size);
61*eca53ba6SRoland Levillain   }
62*eca53ba6SRoland Levillain   return false;
63*eca53ba6SRoland Levillain }
64*eca53ba6SRoland Levillain 
CpuFeatures_StringView_StartsWith(const StringView a,const StringView b)65*eca53ba6SRoland Levillain bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
66*eca53ba6SRoland Levillain   return a.ptr && b.ptr && b.size && a.size >= b.size
67*eca53ba6SRoland Levillain              ? equals(a.ptr, b.ptr, b.size)
68*eca53ba6SRoland Levillain              : false;
69*eca53ba6SRoland Levillain }
70*eca53ba6SRoland Levillain 
CpuFeatures_StringView_PopFront(const StringView str_view,size_t count)71*eca53ba6SRoland Levillain StringView CpuFeatures_StringView_PopFront(const StringView str_view,
72*eca53ba6SRoland Levillain                                            size_t count) {
73*eca53ba6SRoland Levillain   if (count > str_view.size) {
74*eca53ba6SRoland Levillain     return kEmptyStringView;
75*eca53ba6SRoland Levillain   }
76*eca53ba6SRoland Levillain   return view(str_view.ptr + count, str_view.size - count);
77*eca53ba6SRoland Levillain }
78*eca53ba6SRoland Levillain 
CpuFeatures_StringView_PopBack(const StringView str_view,size_t count)79*eca53ba6SRoland Levillain StringView CpuFeatures_StringView_PopBack(const StringView str_view,
80*eca53ba6SRoland Levillain                                           size_t count) {
81*eca53ba6SRoland Levillain   if (count > str_view.size) {
82*eca53ba6SRoland Levillain     return kEmptyStringView;
83*eca53ba6SRoland Levillain   }
84*eca53ba6SRoland Levillain   return view(str_view.ptr, str_view.size - count);
85*eca53ba6SRoland Levillain }
86*eca53ba6SRoland Levillain 
CpuFeatures_StringView_KeepFront(const StringView str_view,size_t count)87*eca53ba6SRoland Levillain StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
88*eca53ba6SRoland Levillain                                             size_t count) {
89*eca53ba6SRoland Levillain   return count <= str_view.size ? view(str_view.ptr, count) : str_view;
90*eca53ba6SRoland Levillain }
91*eca53ba6SRoland Levillain 
CpuFeatures_StringView_Front(const StringView view)92*eca53ba6SRoland Levillain char CpuFeatures_StringView_Front(const StringView view) {
93*eca53ba6SRoland Levillain   assert(view.size);
94*eca53ba6SRoland Levillain   assert(view.ptr);
95*eca53ba6SRoland Levillain   return view.ptr[0];
96*eca53ba6SRoland Levillain }
97*eca53ba6SRoland Levillain 
CpuFeatures_StringView_Back(const StringView view)98*eca53ba6SRoland Levillain char CpuFeatures_StringView_Back(const StringView view) {
99*eca53ba6SRoland Levillain   assert(view.size);
100*eca53ba6SRoland Levillain   return view.ptr[view.size - 1];
101*eca53ba6SRoland Levillain }
102*eca53ba6SRoland Levillain 
CpuFeatures_StringView_TrimWhitespace(StringView view)103*eca53ba6SRoland Levillain StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
104*eca53ba6SRoland Levillain   while (view.size && isspace(CpuFeatures_StringView_Front(view)))
105*eca53ba6SRoland Levillain     view = CpuFeatures_StringView_PopFront(view, 1);
106*eca53ba6SRoland Levillain   while (view.size && isspace(CpuFeatures_StringView_Back(view)))
107*eca53ba6SRoland Levillain     view = CpuFeatures_StringView_PopBack(view, 1);
108*eca53ba6SRoland Levillain   return view;
109*eca53ba6SRoland Levillain }
110*eca53ba6SRoland Levillain 
HexValue(const char c)111*eca53ba6SRoland Levillain static int HexValue(const char c) {
112*eca53ba6SRoland Levillain   if (c >= '0' && c <= '9') return c - '0';
113*eca53ba6SRoland Levillain   if (c >= 'a' && c <= 'f') return c - 'a' + 10;
114*eca53ba6SRoland Levillain   if (c >= 'A' && c <= 'F') return c - 'A' + 10;
115*eca53ba6SRoland Levillain   return -1;
116*eca53ba6SRoland Levillain }
117*eca53ba6SRoland Levillain 
118*eca53ba6SRoland Levillain // Returns -1 if view contains non digits.
ParsePositiveNumberWithBase(const StringView view,int base)119*eca53ba6SRoland Levillain static int ParsePositiveNumberWithBase(const StringView view, int base) {
120*eca53ba6SRoland Levillain   int result = 0;
121*eca53ba6SRoland Levillain   StringView remainder = view;
122*eca53ba6SRoland Levillain   for (; remainder.size;
123*eca53ba6SRoland Levillain        remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
124*eca53ba6SRoland Levillain     const int value = HexValue(CpuFeatures_StringView_Front(remainder));
125*eca53ba6SRoland Levillain     if (value < 0 || value >= base) return -1;
126*eca53ba6SRoland Levillain     result = (result * base) + value;
127*eca53ba6SRoland Levillain   }
128*eca53ba6SRoland Levillain   return result;
129*eca53ba6SRoland Levillain }
130*eca53ba6SRoland Levillain 
CpuFeatures_StringView_ParsePositiveNumber(const StringView view)131*eca53ba6SRoland Levillain int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
132*eca53ba6SRoland Levillain   if (view.size) {
133*eca53ba6SRoland Levillain     const StringView hex_prefix = str("0x");
134*eca53ba6SRoland Levillain     if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
135*eca53ba6SRoland Levillain       const StringView span_no_prefix =
136*eca53ba6SRoland Levillain           CpuFeatures_StringView_PopFront(view, hex_prefix.size);
137*eca53ba6SRoland Levillain       return ParsePositiveNumberWithBase(span_no_prefix, 16);
138*eca53ba6SRoland Levillain     }
139*eca53ba6SRoland Levillain     return ParsePositiveNumberWithBase(view, 10);
140*eca53ba6SRoland Levillain   }
141*eca53ba6SRoland Levillain   return -1;
142*eca53ba6SRoland Levillain }
143*eca53ba6SRoland Levillain 
CpuFeatures_StringView_CopyString(const StringView src,char * dst,size_t dst_size)144*eca53ba6SRoland Levillain void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
145*eca53ba6SRoland Levillain                                        size_t dst_size) {
146*eca53ba6SRoland Levillain   if (dst_size > 0) {
147*eca53ba6SRoland Levillain     const size_t max_copy_size = dst_size - 1;
148*eca53ba6SRoland Levillain     const size_t copy_size =
149*eca53ba6SRoland Levillain         src.size > max_copy_size ? max_copy_size : src.size;
150*eca53ba6SRoland Levillain     copy(dst, src.ptr, copy_size);
151*eca53ba6SRoland Levillain     dst[copy_size] = '\0';
152*eca53ba6SRoland Levillain   }
153*eca53ba6SRoland Levillain }
154*eca53ba6SRoland Levillain 
CpuFeatures_StringView_HasWord(const StringView line,const char * const word_str,const char separator)155*eca53ba6SRoland Levillain bool CpuFeatures_StringView_HasWord(const StringView line,
156*eca53ba6SRoland Levillain                                     const char* const word_str,
157*eca53ba6SRoland Levillain                                     const char separator) {
158*eca53ba6SRoland Levillain   const StringView word = str(word_str);
159*eca53ba6SRoland Levillain   StringView remainder = line;
160*eca53ba6SRoland Levillain   for (;;) {
161*eca53ba6SRoland Levillain     const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
162*eca53ba6SRoland Levillain     if (index_of_word < 0) {
163*eca53ba6SRoland Levillain       return false;
164*eca53ba6SRoland Levillain     } else {
165*eca53ba6SRoland Levillain       const StringView before =
166*eca53ba6SRoland Levillain           CpuFeatures_StringView_KeepFront(line, index_of_word);
167*eca53ba6SRoland Levillain       const StringView after =
168*eca53ba6SRoland Levillain           CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
169*eca53ba6SRoland Levillain       const bool valid_before =
170*eca53ba6SRoland Levillain           before.size == 0 || CpuFeatures_StringView_Back(before) == separator;
171*eca53ba6SRoland Levillain       const bool valid_after =
172*eca53ba6SRoland Levillain           after.size == 0 || CpuFeatures_StringView_Front(after) == separator;
173*eca53ba6SRoland Levillain       if (valid_before && valid_after) return true;
174*eca53ba6SRoland Levillain       remainder =
175*eca53ba6SRoland Levillain           CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
176*eca53ba6SRoland Levillain     }
177*eca53ba6SRoland Levillain   }
178*eca53ba6SRoland Levillain   return false;
179*eca53ba6SRoland Levillain }
180*eca53ba6SRoland Levillain 
CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,StringView * key,StringView * value)181*eca53ba6SRoland Levillain bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
182*eca53ba6SRoland Levillain                                                  StringView* key,
183*eca53ba6SRoland Levillain                                                  StringView* value) {
184*eca53ba6SRoland Levillain   const StringView sep = str(": ");
185*eca53ba6SRoland Levillain   const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
186*eca53ba6SRoland Levillain   if (index_of_separator < 0) return false;
187*eca53ba6SRoland Levillain   *value = CpuFeatures_StringView_TrimWhitespace(
188*eca53ba6SRoland Levillain       CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size));
189*eca53ba6SRoland Levillain   *key = CpuFeatures_StringView_TrimWhitespace(
190*eca53ba6SRoland Levillain       CpuFeatures_StringView_KeepFront(line, index_of_separator));
191*eca53ba6SRoland Levillain   return true;
192*eca53ba6SRoland Levillain }
193