blob: dc3158fff266f4e162c1f8d32583c06ad183fe9e [file] [log] [blame]
Guillaume Chatelet3cc8f312020-10-12 08:55:20 +00001// Copyright 2017 Google LLC
Guillaume Chatelet439d3712018-02-01 10:03:09 +01002//
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
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020021int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010022 if (view.ptr && view.size) {
23 const char* const found = (const char*)memchr(view.ptr, c, view.size);
24 if (found) {
Leonard Mosescubdb36d92019-07-03 05:57:19 -070025 return (int)(found - view.ptr);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010026 }
27 }
28 return -1;
29}
30
Arvid Gerstmannd9689912018-05-04 09:32:17 +020031int CpuFeatures_StringView_IndexOf(const StringView view,
32 const StringView sub_view) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010033 if (sub_view.size) {
34 StringView remainder = view;
35 while (remainder.size >= sub_view.size) {
Arvid Gerstmannd9689912018-05-04 09:32:17 +020036 const int found_index =
37 CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010038 if (found_index < 0) break;
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020039 remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
40 if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
Leonard Mosescubdb36d92019-07-03 05:57:19 -070041 return (int)(remainder.ptr - view.ptr);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010042 }
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020043 remainder = CpuFeatures_StringView_PopFront(remainder, 1);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010044 }
45 }
46 return -1;
47}
48
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020049bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010050 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
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020056bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010057 return a.ptr && b.ptr && b.size && a.size >= b.size
58 ? memcmp(a.ptr, b.ptr, b.size) == 0
59 : false;
60}
61
Arvid Gerstmannd9689912018-05-04 09:32:17 +020062StringView CpuFeatures_StringView_PopFront(const StringView str_view,
63 size_t count) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010064 if (count > str_view.size) {
65 return kEmptyStringView;
66 }
67 return view(str_view.ptr + count, str_view.size - count);
68}
69
Arvid Gerstmannd9689912018-05-04 09:32:17 +020070StringView CpuFeatures_StringView_PopBack(const StringView str_view,
71 size_t count) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010072 if (count > str_view.size) {
73 return kEmptyStringView;
74 }
75 return view(str_view.ptr, str_view.size - count);
76}
77
Arvid Gerstmannd9689912018-05-04 09:32:17 +020078StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
79 size_t count) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010080 return count <= str_view.size ? view(str_view.ptr, count) : str_view;
81}
82
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020083char CpuFeatures_StringView_Front(const StringView view) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010084 assert(view.size);
85 assert(view.ptr);
86 return view.ptr[0];
87}
88
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020089char CpuFeatures_StringView_Back(const StringView view) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010090 assert(view.size);
91 return view.ptr[view.size - 1];
92}
93
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020094StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
Arvid Gerstmannd9689912018-05-04 09:32:17 +020095 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);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010099 return view;
100}
101
102static 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.
110static int ParsePositiveNumberWithBase(const StringView view, int base) {
111 int result = 0;
112 StringView remainder = view;
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200113 for (; remainder.size;
114 remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +0200115 const int value = HexValue(CpuFeatures_StringView_Front(remainder));
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100116 if (value < 0 || value >= base) return -1;
117 result = (result * base) + value;
118 }
119 return result;
120}
121
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +0200122int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100123 if (view.size) {
124 const StringView hex_prefix = str("0x");
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +0200125 if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200126 const StringView span_no_prefix =
127 CpuFeatures_StringView_PopFront(view, hex_prefix.size);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100128 return ParsePositiveNumberWithBase(span_no_prefix, 16);
129 }
130 return ParsePositiveNumberWithBase(view, 10);
131 }
132 return -1;
133}
134
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200135void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
136 size_t dst_size) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100137 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
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200146bool CpuFeatures_StringView_HasWord(const StringView line,
147 const char* const word_str) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100148 const StringView word = str(word_str);
149 StringView remainder = line;
150 for (;;) {
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +0200151 const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100152 if (index_of_word < 0) {
153 return false;
154 } else {
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200155 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) == ' ';
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100163 if (valid_before && valid_after) return true;
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200164 remainder =
165 CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100166 }
167 }
168 return false;
169}
170
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200171bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
172 StringView* key,
173 StringView* value) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100174 const StringView sep = str(": ");
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +0200175 const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100176 if (index_of_separator < 0) return false;
Arvid Gerstmannd9689912018-05-04 09:32:17 +0200177 *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));
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100181 return true;
182}