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