|
@@ -0,0 +1,174 @@
|
|
|
|
|
+#ifndef STR_H
|
|
|
|
|
+#define STR_H
|
|
|
|
|
+
|
|
|
|
|
+#include <stdint.h>
|
|
|
|
|
+#include <stddef.h>
|
|
|
|
|
+#include <stdbool.h>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+struct str {
|
|
|
|
|
+ const char *data;
|
|
|
|
|
+ size_t size;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const struct str STR_EMPTY = {"", 0};
|
|
|
|
|
+
|
|
|
|
|
+struct str_tokenizer {
|
|
|
|
|
+ struct str str;
|
|
|
|
|
+ size_t cur;
|
|
|
|
|
+ char c;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct str str_from_cstr(const char *cstr, size_t cstr_size);
|
|
|
|
|
+struct str str_rstrip(struct str str);
|
|
|
|
|
+struct str str_lstrip(struct str str);
|
|
|
|
|
+struct str str_strip(struct str str);
|
|
|
|
|
+
|
|
|
|
|
+struct str_tokenizer str_tokenize(struct str str, char c);
|
|
|
|
|
+struct str str_tokenizer_next(struct str_tokenizer *st);
|
|
|
|
|
+
|
|
|
|
|
+struct str str_slice(struct str str, size_t from, size_t to);
|
|
|
|
|
+
|
|
|
|
|
+bool str_eq_cstr(struct str str, const char *cstr, size_t cstr_size);
|
|
|
|
|
+
|
|
|
|
|
+#if defined(IMP) || defined(IMP_STR)
|
|
|
|
|
+
|
|
|
|
|
+#include <ctype.h>
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_from_cstr(const char *cstr, size_t cstr_size)
|
|
|
|
|
+{
|
|
|
|
|
+ struct str str;
|
|
|
|
|
+ str.data = cstr;
|
|
|
|
|
+ str.size = cstr_size;
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_rstrip(struct str str)
|
|
|
|
|
+{
|
|
|
|
|
+ while ( isspace(str.data[str.size-1]) ) {
|
|
|
|
|
+ --str.size;
|
|
|
|
|
+ }
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_lstrip(struct str str)
|
|
|
|
|
+{
|
|
|
|
|
+ while ( isspace(*str.data) ) {
|
|
|
|
|
+ ++str.data;
|
|
|
|
|
+ --str.size;
|
|
|
|
|
+ }
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_strip(struct str str)
|
|
|
|
|
+{
|
|
|
|
|
+ return str_lstrip(str_rstrip(str));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str_tokenizer
|
|
|
|
|
+str_tokenize(struct str str, char c)
|
|
|
|
|
+{
|
|
|
|
|
+ struct str_tokenizer st = {0};
|
|
|
|
|
+ st.str = str;
|
|
|
|
|
+ st.c = c;
|
|
|
|
|
+ return st;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_tokenizer_next(struct str_tokenizer *st)
|
|
|
|
|
+{
|
|
|
|
|
+ struct str str;
|
|
|
|
|
+
|
|
|
|
|
+ if ( st == NULL ) {
|
|
|
|
|
+ goto ret_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( st->cur >= st->str.size ) {
|
|
|
|
|
+ goto ret_done;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( st->str.data[st->cur] == '\0' ) {
|
|
|
|
|
+ goto ret_done;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ str = st->str;
|
|
|
|
|
+ str.data += st->cur;
|
|
|
|
|
+ str.size = 0;
|
|
|
|
|
+
|
|
|
|
|
+ while ( str.data[str.size] != st->c
|
|
|
|
|
+ && st->cur < st->str.size ) {
|
|
|
|
|
+ ++str.size;
|
|
|
|
|
+ ++st->cur;
|
|
|
|
|
+ }
|
|
|
|
|
+ ++st->cur;
|
|
|
|
|
+
|
|
|
|
|
+ if ( str.size == 0 ) {
|
|
|
|
|
+ goto ret_empty;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return str;
|
|
|
|
|
+
|
|
|
|
|
+ret_empty:
|
|
|
|
|
+ str.data = "";
|
|
|
|
|
+ str.size = 0;
|
|
|
|
|
+ return str;
|
|
|
|
|
+
|
|
|
|
|
+ret_done:
|
|
|
|
|
+ str.data = "";
|
|
|
|
|
+ str.size = (size_t) -1;
|
|
|
|
|
+ return str;
|
|
|
|
|
+
|
|
|
|
|
+ret_err:
|
|
|
|
|
+ str.data = "";
|
|
|
|
|
+ str.size = (size_t) -2;
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct str
|
|
|
|
|
+str_slice(struct str str, size_t from, size_t to)
|
|
|
|
|
+{
|
|
|
|
|
+ if ( from > str.size ) {
|
|
|
|
|
+ goto ret_err;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ( from > to ) {
|
|
|
|
|
+ goto ret_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ to = ( to > str.size ) * str.size \
|
|
|
|
|
+ + ( to <= str.size ) * to;
|
|
|
|
|
+
|
|
|
|
|
+ str.data += from;
|
|
|
|
|
+ str.size = to - from;
|
|
|
|
|
+
|
|
|
|
|
+ return str;
|
|
|
|
|
+
|
|
|
|
|
+ret_err:
|
|
|
|
|
+ str.data = "";
|
|
|
|
|
+ str.size = (size_t) -2;
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool
|
|
|
|
|
+str_eq_cstr(struct str str, const char *cstr, size_t cstr_size)
|
|
|
|
|
+{
|
|
|
|
|
+ size_t i = 0;
|
|
|
|
|
+ if ( str.size != cstr_size ) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for ( i = 0; i < str.size; ++i ) {
|
|
|
|
|
+ if ( str.data[i] != cstr[i] ) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif /* defined(IMP) || defined(IMP_STR) */
|
|
|
|
|
+
|
|
|
|
|
+#endif /* STR_H */
|