1*6a6cfa5dSJason King /*
2*6a6cfa5dSJason King  * This file and its contents are supplied under the terms of the
3*6a6cfa5dSJason King  * Common Development and Distribution License ("CDDL"), version 1.0.
4*6a6cfa5dSJason King  * You may only use this file in accordance with the terms of version
5*6a6cfa5dSJason King  * 1.0 of the CDDL.
6*6a6cfa5dSJason King  *
7*6a6cfa5dSJason King  * A full copy of the text of the CDDL should have accompanied this
8*6a6cfa5dSJason King  * source.  A copy of the CDDL is also available via the Internet at
9*6a6cfa5dSJason King  * http://www.illumos.org/license/CDDL.
10*6a6cfa5dSJason King  */
11*6a6cfa5dSJason King 
12*6a6cfa5dSJason King /*
13*6a6cfa5dSJason King  * Copyright 2019, Joyent, Inc.
14*6a6cfa5dSJason King  */
15*6a6cfa5dSJason King 
16*6a6cfa5dSJason King #ifndef _STRVIEW_H
17*6a6cfa5dSJason King #define	_STRVIEW_H
18*6a6cfa5dSJason King 
19*6a6cfa5dSJason King #include <inttypes.h>
20*6a6cfa5dSJason King 
21*6a6cfa5dSJason King #ifdef __cplusplus
22*6a6cfa5dSJason King extern "C" {
23*6a6cfa5dSJason King #endif
24*6a6cfa5dSJason King 
25*6a6cfa5dSJason King /*
26*6a6cfa5dSJason King  * strview_t's represent a read-only subset of a string.  It is somewhat
27*6a6cfa5dSJason King  * similar to the concept of ranges found in other languages in that one can
28*6a6cfa5dSJason King  * create a strview_t, and then create a smaller range for iteration.
29*6a6cfa5dSJason King  *
30*6a6cfa5dSJason King  * sv_first is the address of the first location (and is advanced as values
31*6a6cfa5dSJason King  * are consumed) in the string.
32*6a6cfa5dSJason King  *
33*6a6cfa5dSJason King  * sv_last is the address one byte after the last valid value of the subset.
34*6a6cfa5dSJason King  * Basically, the length of the range is equal to 'sv_last - sv_first'.  For
35*6a6cfa5dSJason King  * example, in the string 'abcdef' to create a view 'bcd', *sv_first would
36*6a6cfa5dSJason King  * equal 'b' and *sv_last would equal 'e'.
37*6a6cfa5dSJason King  *
38*6a6cfa5dSJason King  * sv_rem is the number of bytes remaining in the range.
39*6a6cfa5dSJason King  *
40*6a6cfa5dSJason King  * A strview_t maintains references to the underlying string, so the lifetime
41*6a6cfa5dSJason King  * of a strview_t should be equal to or less than the underlying string (i.e.
42*6a6cfa5dSJason King  * it doesn't copy the data from the underlying string, but maintains pointers
43*6a6cfa5dSJason King  * to the original data).
44*6a6cfa5dSJason King  *
45*6a6cfa5dSJason King  * While the underlying string does not need to be NUL-terminated, NUL is still
46*6a6cfa5dSJason King  * used as a sentinel value in some instances (e.g. sv_peek()), and should not
47*6a6cfa5dSJason King  * be contained within the defined range.
48*6a6cfa5dSJason King  *
49*6a6cfa5dSJason King  * As hinted above, the functions currently do not deal with multi-byte
50*6a6cfa5dSJason King  * characters, i.e. each character is assumed to be a single byte.  The
51*6a6cfa5dSJason King  * current consumers do not need to handle multi-byte characters (UTF-8
52*6a6cfa5dSJason King  * or otherwise), so this is sufficient at the current time.
53*6a6cfa5dSJason King  */
54*6a6cfa5dSJason King typedef struct strview {
55*6a6cfa5dSJason King 	const char *sv_first;
56*6a6cfa5dSJason King 	const char *sv_last;
57*6a6cfa5dSJason King 	size_t sv_rem;
58*6a6cfa5dSJason King } strview_t;
59*6a6cfa5dSJason King 
60*6a6cfa5dSJason King /*
61*6a6cfa5dSJason King  * SV_PRINT() is used for printing strview_t values during debugging, e.g.
62*6a6cfa5dSJason King  * `DEMDEBUG("%*.s", SV_PRINT(sv));`
63*6a6cfa5dSJason King  */
64*6a6cfa5dSJason King #define	SV_PRINT(_sv)	(int)(_sv)->sv_rem, (_sv)->sv_first
65*6a6cfa5dSJason King 
66*6a6cfa5dSJason King /*
67*6a6cfa5dSJason King  * Initialize a strview_t from an already initialized strview_t -- the state of
68*6a6cfa5dSJason King  * the source strview_t is duplicated in the newly initialized strview_t.
69*6a6cfa5dSJason King  */
70*6a6cfa5dSJason King void sv_init_sv(strview_t *, const strview_t *);
71*6a6cfa5dSJason King 
72*6a6cfa5dSJason King /*
73*6a6cfa5dSJason King  * Initialize a strview_t as a subset of an already initialized strview_t.
74*6a6cfa5dSJason King  * The size of the subset (size_t) must be <= sv_remaining(src).
75*6a6cfa5dSJason King  */
76*6a6cfa5dSJason King void sv_init_sv_range(strview_t *, const strview_t *, size_t);
77*6a6cfa5dSJason King 
78*6a6cfa5dSJason King /*
79*6a6cfa5dSJason King  * Initialize a strview_t from a string.  The two const char * pointers are the
80*6a6cfa5dSJason King  * sv_first and sv_last values to use (see above).  If the source string is
81*6a6cfa5dSJason King  * NUL-terminated, one can optionally pass NULL for the second parameter in
82*6a6cfa5dSJason King  * which case, the entire NUL-terminated string (starting at sv_first) is
83*6a6cfa5dSJason King  * treated as a strview_t.
84*6a6cfa5dSJason King  */
85*6a6cfa5dSJason King void sv_init_str(strview_t *, const char *, const char *);
86*6a6cfa5dSJason King 
87*6a6cfa5dSJason King /*
88*6a6cfa5dSJason King  * Return the number of bytes remaining to consume in the strview_t
89*6a6cfa5dSJason King  */
90*6a6cfa5dSJason King size_t sv_remaining(const strview_t *);
91*6a6cfa5dSJason King 
92*6a6cfa5dSJason King /*
93*6a6cfa5dSJason King  * Return the char at the given position in the strview_t (without advancing
94*6a6cfa5dSJason King  * the position).  Position values >=0 are relative to the current position
95*6a6cfa5dSJason King  * of the strview_t (e.g. '0' will return the next character, '1' will return
96*6a6cfa5dSJason King  * the character after that), while negative position values are relative to
97*6a6cfa5dSJason King  * the end of the strview_t (e.g. '-1' will return the last character, '-2'
98*6a6cfa5dSJason King  * will return the second to last character).
99*6a6cfa5dSJason King  *
100*6a6cfa5dSJason King  * If the position value is out of range, '\0' is returned.
101*6a6cfa5dSJason King  */
102*6a6cfa5dSJason King char sv_peek(const strview_t *, ssize_t);
103*6a6cfa5dSJason King 
104*6a6cfa5dSJason King /*
105*6a6cfa5dSJason King  * Return the next character and advance the strview_t position.  If no more
106*6a6cfa5dSJason King  * characters are available, '\0' is returned.
107*6a6cfa5dSJason King  */
108*6a6cfa5dSJason King char sv_consume_c(strview_t *);
109*6a6cfa5dSJason King 
110*6a6cfa5dSJason King /*
111*6a6cfa5dSJason King  * Advance the position of the strview_t by the given number of bytes.  The
112*6a6cfa5dSJason King  * amount must be <= the number of bytes remaining in the strview_t.
113*6a6cfa5dSJason King  */
114*6a6cfa5dSJason King void sv_consume_n(strview_t *, size_t);
115*6a6cfa5dSJason King 
116*6a6cfa5dSJason King /*
117*6a6cfa5dSJason King  * Advance the strview_t position if the bytes of the strview starting at the
118*6a6cfa5dSJason King  * current position match the given NUL-terminated string.  The length of the
119*6a6cfa5dSJason King  * NUL-terminated string must be <= the number of bytes remaining in the
120*6a6cfa5dSJason King  * strview_t.
121*6a6cfa5dSJason King  *
122*6a6cfa5dSJason King  * If there is a match, the position of the strview_t is advanced by the
123*6a6cfa5dSJason King  * length of the NUL-terminated comparison string, and B_TRUE is returned. If
124*6a6cfa5dSJason King  * there is no match, the position is not advanced and B_FALSE is returned.
125*6a6cfa5dSJason King  */
126*6a6cfa5dSJason King boolean_t sv_consume_if(strview_t *, const char *);
127*6a6cfa5dSJason King 
128*6a6cfa5dSJason King /*
129*6a6cfa5dSJason King  * Advance the position of the strview_t if the next char in the strview_t
130*6a6cfa5dSJason King  * is equal to the given char.  If there is a match, the strview_t position
131*6a6cfa5dSJason King  * is advanced one byte and B_TRUE is returned.  If they do not match, B_FALSE
132*6a6cfa5dSJason King  * is returned and the position is not advanced.
133*6a6cfa5dSJason King  */
134*6a6cfa5dSJason King boolean_t sv_consume_if_c(strview_t *, char);
135*6a6cfa5dSJason King 
136*6a6cfa5dSJason King #ifdef __cplusplus
137*6a6cfa5dSJason King }
138*6a6cfa5dSJason King #endif
139*6a6cfa5dSJason King 
140*6a6cfa5dSJason King #endif /* _STRVIEW_H */
141