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