• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google LLC
2 //
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 #include "internal/string_view.h"
16 
17 #include <assert.h>
18 #include <ctype.h>
19 #include <string.h>
20 
CpuFeatures_StringView_IndexOfChar(const StringView view,char c)21 int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
22   if (view.ptr && view.size) {
23     const char* const found = (const char*)memchr(view.ptr, c, view.size);
24     if (found) {
25       return (int)(found - view.ptr);
26     }
27   }
28   return -1;
29 }
30 
CpuFeatures_StringView_IndexOf(const StringView view,const StringView sub_view)31 int CpuFeatures_StringView_IndexOf(const StringView view,
32                                    const StringView sub_view) {
33   if (sub_view.size) {
34     StringView remainder = view;
35     while (remainder.size >= sub_view.size) {
36       const int found_index =
37           CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
38       if (found_index < 0) break;
39       remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
40       if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
41         return (int)(remainder.ptr - view.ptr);
42       }
43       remainder = CpuFeatures_StringView_PopFront(remainder, 1);
44     }
45   }
46   return -1;
47 }
48 
CpuFeatures_StringView_IsEquals(const StringView a,const StringView b)49 bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
50   if (a.size == b.size) {
51     return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0;
52   }
53   return false;
54 }
55 
CpuFeatures_StringView_StartsWith(const StringView a,const StringView b)56 bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
57   return a.ptr && b.ptr && b.size && a.size >= b.size
58              ? memcmp(a.ptr, b.ptr, b.size) == 0
59              : false;
60 }
61 
CpuFeatures_StringView_PopFront(const StringView str_view,size_t count)62 StringView CpuFeatures_StringView_PopFront(const StringView str_view,
63                                            size_t count) {
64   if (count > str_view.size) {
65     return kEmptyStringView;
66   }
67   return view(str_view.ptr + count, str_view.size - count);
68 }
69 
CpuFeatures_StringView_PopBack(const StringView str_view,size_t count)70 StringView CpuFeatures_StringView_PopBack(const StringView str_view,
71                                           size_t count) {
72   if (count > str_view.size) {
73     return kEmptyStringView;
74   }
75   return view(str_view.ptr, str_view.size - count);
76 }
77 
CpuFeatures_StringView_KeepFront(const StringView str_view,size_t count)78 StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
79                                             size_t count) {
80   return count <= str_view.size ? view(str_view.ptr, count) : str_view;
81 }
82 
CpuFeatures_StringView_Front(const StringView view)83 char CpuFeatures_StringView_Front(const StringView view) {
84   assert(view.size);
85   assert(view.ptr);
86   return view.ptr[0];
87 }
88 
CpuFeatures_StringView_Back(const StringView view)89 char CpuFeatures_StringView_Back(const StringView view) {
90   assert(view.size);
91   return view.ptr[view.size - 1];
92 }
93 
CpuFeatures_StringView_TrimWhitespace(StringView view)94 StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
95   while (view.size && isspace(CpuFeatures_StringView_Front(view)))
96     view = CpuFeatures_StringView_PopFront(view, 1);
97   while (view.size && isspace(CpuFeatures_StringView_Back(view)))
98     view = CpuFeatures_StringView_PopBack(view, 1);
99   return view;
100 }
101 
HexValue(const char c)102 static int HexValue(const char c) {
103   if (c >= '0' && c <= '9') return c - '0';
104   if (c >= 'a' && c <= 'f') return c - 'a' + 10;
105   if (c >= 'A' && c <= 'F') return c - 'A' + 10;
106   return -1;
107 }
108 
109 // Returns -1 if view contains non digits.
ParsePositiveNumberWithBase(const StringView view,int base)110 static int ParsePositiveNumberWithBase(const StringView view, int base) {
111   int result = 0;
112   StringView remainder = view;
113   for (; remainder.size;
114        remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
115     const int value = HexValue(CpuFeatures_StringView_Front(remainder));
116     if (value < 0 || value >= base) return -1;
117     result = (result * base) + value;
118   }
119   return result;
120 }
121 
CpuFeatures_StringView_ParsePositiveNumber(const StringView view)122 int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
123   if (view.size) {
124     const StringView hex_prefix = str("0x");
125     if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
126       const StringView span_no_prefix =
127           CpuFeatures_StringView_PopFront(view, hex_prefix.size);
128       return ParsePositiveNumberWithBase(span_no_prefix, 16);
129     }
130     return ParsePositiveNumberWithBase(view, 10);
131   }
132   return -1;
133 }
134 
CpuFeatures_StringView_CopyString(const StringView src,char * dst,size_t dst_size)135 void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
136                                        size_t dst_size) {
137   if (dst_size > 0) {
138     const size_t max_copy_size = dst_size - 1;
139     const size_t copy_size =
140         src.size > max_copy_size ? max_copy_size : src.size;
141     memcpy(dst, src.ptr, copy_size);
142     dst[copy_size] = '\0';
143   }
144 }
145 
CpuFeatures_StringView_HasWord(const StringView line,const char * const word_str)146 bool CpuFeatures_StringView_HasWord(const StringView line,
147                                     const char* const word_str) {
148   const StringView word = str(word_str);
149   StringView remainder = line;
150   for (;;) {
151     const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
152     if (index_of_word < 0) {
153       return false;
154     } else {
155       const StringView before =
156           CpuFeatures_StringView_KeepFront(line, index_of_word);
157       const StringView after =
158           CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
159       const bool valid_before =
160           before.size == 0 || CpuFeatures_StringView_Back(before) == ' ';
161       const bool valid_after =
162           after.size == 0 || CpuFeatures_StringView_Front(after) == ' ';
163       if (valid_before && valid_after) return true;
164       remainder =
165           CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
166     }
167   }
168   return false;
169 }
170 
CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,StringView * key,StringView * value)171 bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
172                                                  StringView* key,
173                                                  StringView* value) {
174   const StringView sep = str(": ");
175   const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
176   if (index_of_separator < 0) return false;
177   *value = CpuFeatures_StringView_TrimWhitespace(
178       CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size));
179   *key = CpuFeatures_StringView_TrimWhitespace(
180       CpuFeatures_StringView_KeepFront(line, index_of_separator));
181   return true;
182 }
183