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