1 /*
2  * Copyright 2018 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include "hf/memiter.h"
10 
11 #include "hf/check.h"
12 #include "hf/dlog.h"
13 #include "hf/std.h"
14 
15 /**
16  * Initialises the given memory iterator.
17  */
memiter_init(struct memiter * it,const void * data,size_t size)18 void memiter_init(struct memiter *it, const void *data, size_t size)
19 {
20 	it->next = data;
21 	it->limit = it->next + size;
22 }
23 
24 /**
25  * Determines if the next character is a whitespace.
26  */
memiter_isspace(struct memiter * it)27 static bool memiter_isspace(struct memiter *it)
28 {
29 	switch (*it->next) {
30 	case ' ':
31 	case '\t':
32 	case '\n':
33 	case '\r':
34 		return true;
35 	default:
36 		return false;
37 	}
38 }
39 
40 /**
41  * Moves iterator to the next non-whitespace character.
42  */
memiter_skip_space(struct memiter * it)43 static void memiter_skip_space(struct memiter *it)
44 {
45 	while (it->next < it->limit && memiter_isspace(it)) {
46 		it->next++;
47 	}
48 }
49 
50 /**
51  * Compares the iterator to a null-terminated string.
52  */
memiter_iseq(const struct memiter * it,const char * str)53 bool memiter_iseq(const struct memiter *it, const char *str)
54 {
55 	size_t it_len = it->limit - it->next;
56 	size_t len = strnlen_s(str, it_len + 1);
57 
58 	if (len != it_len) {
59 		return false;
60 	}
61 
62 	return memcmp(it->next, str, len) == 0;
63 }
64 
65 /**
66  * Retrieves the next string that is delimited by whitespaces. The result is
67  * stored in "str".
68  */
memiter_parse_str(struct memiter * it,struct memiter * str)69 bool memiter_parse_str(struct memiter *it, struct memiter *str)
70 {
71 	/* Skip all white space and fail if we reach the end of the buffer. */
72 	memiter_skip_space(it);
73 	if (it->next >= it->limit) {
74 		return false;
75 	}
76 
77 	str->next = it->next;
78 
79 	/* Find the end of the string. */
80 	while (it->next < it->limit && !memiter_isspace(it)) {
81 		it->next++;
82 	}
83 
84 	str->limit = it->next;
85 
86 	return true;
87 }
88 
89 /**
90  * Parses the next string that represents a 64-bit number.
91  */
memiter_parse_uint(struct memiter * it,uint64_t * value)92 bool memiter_parse_uint(struct memiter *it, uint64_t *value)
93 {
94 	uint64_t v = 0;
95 
96 	/* Skip all white space and fail if we reach the end of the buffer. */
97 	memiter_skip_space(it);
98 	if (it->next >= it->limit) {
99 		return false;
100 	}
101 
102 	/* Fail if it's not a number. */
103 	if (*it->next < '0' || *it->next > '9') {
104 		return false;
105 	}
106 
107 	/* Parse the number. */
108 	do {
109 		v = v * 10 + *it->next - '0';
110 		it->next++;
111 	} while (it->next < it->limit && *it->next >= '0' && *it->next <= '9');
112 
113 	*value = v;
114 
115 	return true;
116 }
117 
118 /**
119  * Advances the iterator by the given number of bytes. Returns true if the
120  * iterator was advanced without going over its limit; returns false and leaves
121  * the iterator unmodified otherwise.
122  */
memiter_advance(struct memiter * it,size_t v)123 bool memiter_advance(struct memiter *it, size_t v)
124 {
125 	const char *p = it->next + v;
126 
127 	if (p < it->next || p > it->limit) {
128 		return false;
129 	}
130 
131 	it->next = p;
132 	return true;
133 }
134 
135 /**
136  * Decrements the limit of iterator by the given number of bytes. Returns true
137  * if the limit was reduced without going over the base; returns false and
138  * leaves the iterator unmodified otherwise.
139  */
memiter_restrict(struct memiter * it,size_t v)140 bool memiter_restrict(struct memiter *it, size_t v)
141 {
142 	size_t s = memiter_size(it);
143 
144 	if (v > s) {
145 		return false;
146 	}
147 
148 	it->limit = it->next + (s - v);
149 	return true;
150 }
151 
152 /**
153  * Initializes `newit` with the first `v` bytes of `it` and advances `it` by
154  * the same number of bytes. This splits the original range into two iterators
155  * after `v` bytes.
156  * Returns true on success; returns false and leaves `it` unmodified and `newit`
157  * uninitialized otherwise.
158  */
memiter_consume(struct memiter * it,size_t v,struct memiter * newit)159 bool memiter_consume(struct memiter *it, size_t v, struct memiter *newit)
160 {
161 	if (v > memiter_size(it)) {
162 		return false;
163 	}
164 
165 	memiter_init(newit, memiter_base(it), v);
166 	CHECK(memiter_advance(it, v));
167 	return true;
168 }
169 
memiter_base(const struct memiter * it)170 const void *memiter_base(const struct memiter *it)
171 {
172 	return (const void *)it->next;
173 }
174 
175 /**
176  * Returns the number of bytes in interval [it.next, it.limit).
177  */
memiter_size(const struct memiter * it)178 size_t memiter_size(const struct memiter *it)
179 {
180 	return it->limit - it->next;
181 }
182