blob: 6dd9d8c97fb1d59ee0f062e0febaab6b2a7542cb [file] [log] [blame]
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +01001#include "memiter.h"
2
3#include "std.h"
4
5/**
6 * Initialises the given memory iterator.
7 */
8void memiter_init(struct memiter *it, const void *data, size_t size)
9{
10 it->next = data;
11 it->limit = it->next + size;
12}
13
14/**
15 * Determines if the next character is a whitespace.
16 */
17static bool memiter_isspace(struct memiter *it)
18{
19 switch (*it->next) {
20 case ' ':
21 case '\t':
22 case '\n':
23 case '\r':
24 return true;
25 default:
26 return false;
27 }
28}
29
30/**
31 * Moves iterator to the next non-whitespace character.
32 */
33static void memiter_skip_space(struct memiter *it)
34{
35 while (it->next < it->limit && memiter_isspace(it)) {
36 it->next++;
37 }
38}
39
40/**
41 * Compares the iterator to a null-terminated string.
42 */
43bool memiter_iseq(const struct memiter *it, const char *str)
44{
45 size_t len = strlen(str);
46 if (len != it->limit - it->next) {
47 return false;
48 }
49 return memcmp(it->next, str, len) == 0;
50}
51
52/**
53 * Retrieves the next string that is delimited by whitespaces. The result is
54 * stored in "str".
55 */
56bool memiter_parse_str(struct memiter *it, struct memiter *str)
57{
58 /* Skip all white space and fail if we reach the end of the buffer. */
59 memiter_skip_space(it);
60 if (it->next >= it->limit) {
61 return false;
62 }
63
64 str->next = it->next;
65
66 /* Find the end of the string. */
67 while (it->next < it->limit && !memiter_isspace(it)) {
68 it->next++;
69 }
70
71 str->limit = it->next;
72
73 return true;
74}
75
76/**
77 * Parses the next string that represents a 64-bit number.
78 */
79bool memiter_parse_uint(struct memiter *it, uint64_t *value)
80{
81 uint64_t v = 0;
82
83 /* Skip all white space and fail if we reach the end of the buffer. */
84 memiter_skip_space(it);
85 if (it->next >= it->limit) {
86 return false;
87 }
88
89 /* Fail if it's not a number. */
90 if (*it->next < '0' || *it->next > '9') {
91 return false;
92 }
93
94 /* Parse the number. */
95 do {
96 v = v * 10 + *it->next - '0';
97 it->next++;
98 } while (it->next < it->limit && *it->next >= '0' && *it->next <= '9');
99
100 *value = v;
101
102 return true;
103}
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +0100104
105/**
106 * Advances the iterator by the given number of bytes. Returns true if the
107 * iterator was advanced without going over its limit; returns false and leaves
108 * the iterator unmodified otherwise.
109 */
110bool memiter_advance(struct memiter *it, size_t v)
111{
112 const char *p = it->next + v;
113 if (p < it->next || p > it->limit) {
114 return false;
115 }
116 it->next = p;
117 return true;
118}