summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-02-05 13:40:23 +0100
committerTyge Løvset <[email protected]>2021-02-05 13:40:23 +0100
commitc0f80d42f0b8070420fd0f3b81d76007d97cee12 (patch)
tree519d323684f99db5f16de1659fca6eac79f43222
parentdff0972dd98a2a8c46a7bd0bf1308ae06dc670f5 (diff)
downloadSTC-modified-c0f80d42f0b8070420fd0f3b81d76007d97cee12.tar.gz
STC-modified-c0f80d42f0b8070420fd0f3b81d76007d97cee12.zip
Upgraded cstr impl.
-rw-r--r--examples/words.c4
-rw-r--r--stc/ccommon.h8
-rw-r--r--stc/cstr.h106
3 files changed, 61 insertions, 57 deletions
diff --git a/examples/words.c b/examples/words.c
index 08563cfc..b3bd963f 100644
--- a/examples/words.c
+++ b/examples/words.c
@@ -1,4 +1,4 @@
-
+#include <math.h>
#include <stc/cstr.h>
#include <stc/cmap.h>
#include <stc/clist.h>
@@ -16,7 +16,7 @@ int main1()
"this", "sentence", "is", "a", "hoax"
});
- clist_str_push_back(&lwords, cstr_from_fmt("%f", 123897.0 / 23.0));
+ clist_str_push_back(&lwords, cstr_from_fmt("%.15f", sqrt(2)));
c_foreach (w, clist_str, lwords)
printf("%s\n", w.ref->str);
puts("");
diff --git a/stc/ccommon.h b/stc/ccommon.h
index bd2700ab..bea528bc 100644
--- a/stc/ccommon.h
+++ b/stc/ccommon.h
@@ -42,13 +42,13 @@
#if defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
# define STC_API extern
# define STC_DEF
-# define STC_API_V extern
-# define STC_DEF_V
+# define STC_LIBRARY_ONLY(...) __VA_ARGS__
+# define STC_STATIC_ONLY(...)
#else
# define STC_API static inline
# define STC_DEF static inline
-# define STC_API_V static
-# define STC_DEF_V static
+# define STC_LIBRARY_ONLY(...)
+# define STC_STATIC_ONLY(...) __VA_ARGS__
#endif
/* Macro overloading feature support: https://rextester.com/ONP80107 */
diff --git a/stc/cstr.h b/stc/cstr.h
index 8c29c9b3..2a49bbda 100644
--- a/stc/cstr.h
+++ b/stc/cstr.h
@@ -33,11 +33,10 @@
typedef struct cstr { char* str; } cstr_t, cstr;
typedef struct { char *ref; } cstr_iter_t;
typedef char cstr_value_t;
+#define cstr_npos ((size_t) (-1))
-#define cstr_size(s) ((const size_t *) (s).str)[-2]
-#define cstr_capacity(s) ((const size_t *) (s).str)[-1]
-#define cstr_empty(s) (cstr_size(s) == 0)
-#define cstr_npos ((size_t) (-1))
+struct cstr_rep { size_t size, cap; char str[sizeof(size_t)]; };
+#define _cstr_rep(self) c_container_of((self)->str, struct cstr_rep, str)
STC_API cstr_t
cstr_from_n(const char* str, size_t len);
@@ -73,22 +72,21 @@ c_strnfind(const char* s, const char* needle, size_t nmax);
STC_DEF char*
c_istrnfind(const char* s, const char* needle, size_t nmax);
-#define _cstr_rep(self) (((size_t *) (self)->str) - 2)
-#define _cstr_size(s) ((size_t *) (s).str)[-2]
-/* match common malloc_usable_size() sequence: 24, 40, 56, ... */
-#define _cstr_mem(size) ((((size) + 24) >> 4) * 16 + 8)
-/* gives true string capacity: 7, 23, 39, ... */
-#define _cstr_cap(size) ((((size) + 24) >> 4) * 16 - 9)
-static size_t _cstr_nullrep[3] = {0, 0, 0};
+/* optimal memory: based on malloc_usable_size() sequence: 24, 40, 56, ... */
+#define _cstr_opt_mem(cap) ((((offsetof(struct cstr_rep, str) + (cap) + 8)>>4)<<4) + 8)
+/* optimal string capacity: 7, 23, 39, ... */
+#define _cstr_opt_cap(cap) (_cstr_opt_mem(cap) - offsetof(struct cstr_rep, str) - 1)
-static const cstr_t cstr_inits = {(char* ) &_cstr_nullrep[2]};
+STC_LIBRARY_ONLY( extern const cstr_t cstr_inits; )
+STC_STATIC_ONLY( static struct cstr_rep _cstr_nullrep = {0, 0, {0}};
+ static const cstr_t cstr_inits = {_cstr_nullrep.str}; )
STC_INLINE cstr_t
cstr_init() { return cstr_inits; }
STC_INLINE void
cstr_del(cstr_t* self) {
- if (cstr_capacity(*self))
+ if (_cstr_rep(self)->cap)
c_free(_cstr_rep(self));
}
@@ -111,24 +109,24 @@ cstr_from(const char* str) {
STC_INLINE cstr_t
cstr_clone(cstr_t s) {
- return cstr_from_n(s.str, cstr_size(s));
+ return cstr_from_n(s.str, _cstr_rep(&s)->size);
}
STC_INLINE void
cstr_clear(cstr_t* self) {
- self->str[_cstr_size(*self) = 0] = '\0';
+ self->str[_cstr_rep(self)->size = 0] = '\0';
}
STC_INLINE char*
cstr_front(cstr_t* self) {return self->str;}
STC_INLINE char*
-cstr_back(cstr_t* self) {return self->str + _cstr_size(*self) - 1;}
+cstr_back(cstr_t* self) {return self->str + _cstr_rep(self)->size - 1;}
STC_INLINE cstr_iter_t
cstr_begin(cstr_t* self) {cstr_iter_t it = {self->str}; return it;}
STC_INLINE cstr_iter_t
cstr_end(cstr_t* self) {
- cstr_iter_t it = {self->str + cstr_size(*self)}; return it;
+ cstr_iter_t it = {self->str + _cstr_rep(self)->size}; return it;
}
STC_INLINE void cstr_next(cstr_iter_t* it) { ++it->ref; }
STC_INLINE char* cstr_itval(cstr_iter_t it) {return it.ref;}
@@ -140,7 +138,7 @@ cstr_assign(cstr_t* self, const char* str) {
STC_INLINE cstr_t*
cstr_take(cstr_t* self, cstr_t s) {
- if (self->str != s.str && cstr_capacity(*self))
+ if (self->str != s.str && _cstr_rep(self)->cap)
c_free(_cstr_rep(self));
self->str = s.str;
return self;
@@ -163,7 +161,7 @@ cstr_push_back(cstr_t* self, char value) {
STC_INLINE void
cstr_pop_back(cstr_t* self) {
- self->str[ --_cstr_size(*self) ] = '\0';
+ self->str[ --_cstr_rep(self)->size ] = '\0';
}
STC_INLINE void
@@ -188,8 +186,10 @@ cstr_getline(cstr_t *self, FILE *stream) {
/* readonly */
-STC_INLINE size_t
-cstr_length(cstr_t s) { return cstr_size(s); }
+STC_INLINE size_t cstr_size(cstr_t s) {return _cstr_rep(&s)->size;}
+STC_INLINE size_t cstr_capacity(cstr_t s) {return _cstr_rep(&s)->cap;}
+STC_INLINE size_t cstr_empty(cstr_t s) {return _cstr_rep(&s)->size == 0;}
+STC_INLINE size_t cstr_length(cstr_t s) { return _cstr_rep(&s)->size; }
STC_INLINE bool
cstr_equals(cstr_t s1, const char* str) {
@@ -224,24 +224,24 @@ cstr_ibegins_with(cstr_t s, const char* needle) {
STC_INLINE bool
cstr_ends_with(cstr_t s, const char* needle) {
- size_t n = strlen(needle), sz = cstr_size(s);
+ size_t n = strlen(needle), sz = _cstr_rep(&s)->size;
return n <= sz ? memcmp(s.str + sz - n, needle, n) == 0 : false;
}
STC_INLINE bool
cstr_iends_with(cstr_t s, const char* needle) {
- size_t n = strlen(needle), sz = cstr_size(s);
+ size_t n = strlen(needle), sz = _cstr_rep(&s)->size;
return n <= sz ? c_strncasecmp(s.str + sz - n, needle, n) == 0 : false;
}
/* cvec/cmap API functions: */
-STC_INLINE uint32_t c_string_hash(const char* str) {
+STC_INLINE uint32_t
+c_string_hash(const char* str) {
uint32_t hash = 5381, c; /* djb2 */
const uint8_t* p = (const uint8_t*) str;
while ((c = *p++)) hash = ((hash << 5) + hash) ^ c;
return hash;
}
-
STC_INLINE
uint32_t cstr_hash_raw(const char* const* p, size_t none) {
return c_string_hash(*p);
@@ -258,33 +258,37 @@ uint32_t cstr_hash_raw(const char* const* p, size_t none) {
#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
+STC_LIBRARY_ONLY( struct cstr_rep _cstr_nullrep = {0, 0, {0}};
+ const cstr_t cstr_inits = {_cstr_nullrep.str}; )
+
STC_DEF size_t
cstr_reserve(cstr_t* self, size_t cap) {
- size_t oldcap = cstr_capacity(*self);
+ struct cstr_rep* rep = _cstr_rep(self);
+ size_t oldcap = rep->cap;
if (cap > oldcap) {
- size_t* rep = (size_t *) c_realloc(oldcap ? _cstr_rep(self) : NULL, _cstr_mem(cap));
- self->str = (char *) &rep[2];
- if (oldcap == 0) self->str[rep[0] = 0] = '\0';
- return rep[1] = _cstr_cap(cap);
+ rep = (struct cstr_rep*) c_realloc(oldcap ? rep : NULL, _cstr_opt_mem(cap));
+ self->str = rep->str;
+ if (oldcap == 0) self->str[rep->size = 0] = '\0';
+ return (rep->cap = _cstr_opt_cap(cap));
}
return oldcap;
}
STC_DEF void
cstr_resize(cstr_t* self, size_t len, char fill) {
- size_t n = cstr_size(*self);
+ size_t n = _cstr_rep(self)->size;
cstr_reserve(self, len);
if (len > n) memset(self->str + n, fill, len - n);
- if (len | n) self->str[_cstr_size(*self) = len] = '\0';
+ if (len | n) self->str[_cstr_rep(self)->size = len] = '\0';
}
STC_DEF cstr_t
cstr_from_n(const char* str, size_t len) {
if (len == 0) return cstr_inits;
- size_t *rep = (size_t *) c_malloc(_cstr_mem(len));
- cstr_t s = {strncpy((char *) &rep[2], str, len)};
- s.str[rep[0] = len] = '\0';
- rep[1] = _cstr_cap(len);
+ struct cstr_rep* rep = (struct cstr_rep*) c_malloc(_cstr_opt_mem(len));
+ cstr_t s = {strncpy(rep->str, str, len)};
+ s.str[rep->size = len] = '\0';
+ rep->cap = _cstr_opt_cap(len);
return s;
}
@@ -302,7 +306,7 @@ cstr_vfmt(cstr_t* self, const char* fmt, va_list args) {
int len = vsnprintf(NULL, (size_t)0, fmt, args);
cstr_reserve(self, len);
vsprintf(self->str, fmt, args2);
- _cstr_size(*self) = len;
+ _cstr_rep(self)->size = len;
va_end(args2);
}
@@ -329,10 +333,10 @@ cstr_from_fmt(const char* fmt, ...) {
STC_DEF cstr_t*
cstr_assign_n(cstr_t* self, const char* str, size_t len) {
- if (len || cstr_capacity(*self)) {
+ if (len || _cstr_rep(self)->cap) {
cstr_reserve(self, len);
memmove(self->str, str, len);
- self->str[_cstr_size(*self) = len] = '\0';
+ self->str[_cstr_rep(self)->size = len] = '\0';
}
return self;
}
@@ -340,15 +344,15 @@ cstr_assign_n(cstr_t* self, const char* str, size_t len) {
STC_DEF cstr_t*
cstr_append_n(cstr_t* self, const char* str, size_t len) {
if (len) {
- size_t oldlen = cstr_size(*self), newlen = oldlen + len;
- if (newlen > cstr_capacity(*self)) {
+ size_t oldlen = _cstr_rep(self)->size, newlen = oldlen + len;
+ if (newlen > _cstr_rep(self)->cap) {
/* handle self append */
size_t off = (size_t) (str - self->str);
cstr_reserve(self, newlen * 3 / 2);
if (off <= oldlen) str = self->str + off;
}
memcpy(&self->str[oldlen], str, len);
- self->str[_cstr_size(*self) = newlen] = '\0';
+ self->str[_cstr_rep(self)->size = newlen] = '\0';
}
return self;
}
@@ -356,11 +360,11 @@ cstr_append_n(cstr_t* self, const char* str, size_t len) {
STC_INLINE void _cstr_internal_move(cstr_t* self, size_t pos1, size_t pos2) {
if (pos1 == pos2)
return;
- size_t len = cstr_size(*self), newlen = len + pos2 - pos1;
- if (newlen > cstr_capacity(*self))
+ size_t len = _cstr_rep(self)->size, newlen = len + pos2 - pos1;
+ if (newlen > _cstr_rep(self)->cap)
cstr_reserve(self, newlen * 3 / 2);
memmove(&self->str[pos2], &self->str[pos1], len - pos1);
- self->str[_cstr_size(*self) = newlen] = '\0';
+ self->str[_cstr_rep(self)->size = newlen] = '\0';
}
STC_DEF void
@@ -374,16 +378,16 @@ cstr_replace_n(cstr_t* self, size_t pos, size_t len, const char* str, size_t n)
STC_DEF void
cstr_erase_n(cstr_t* self, size_t pos, size_t n) {
- size_t len = cstr_size(*self);
+ size_t len = _cstr_rep(self)->size;
if (len) {
memmove(&self->str[pos], &self->str[pos + n], len - (pos + n));
- self->str[_cstr_size(*self) -= n] = '\0';
+ self->str[_cstr_rep(self)->size -= n] = '\0';
}
}
STC_DEF bool
cstr_getdelim(cstr_t *self, int delim, FILE *fp) {
- size_t pos = 0, cap = cstr_capacity(*self);
+ size_t pos = 0, cap = _cstr_rep(self)->cap;
int c = fgetc(fp);
if (c == EOF)
return false;
@@ -391,7 +395,7 @@ cstr_getdelim(cstr_t *self, int delim, FILE *fp) {
if (pos == cap)
cap = cstr_reserve(self, cap * 3 / 2 + 34);
if (c == delim || c == EOF) {
- self->str[_cstr_size(*self) = pos] = '\0';
+ self->str[_cstr_rep(self)->size = pos] = '\0';
return true;
}
self->str[pos++] = (char) c;
@@ -406,13 +410,13 @@ cstr_find(cstr_t s, const char* needle) {
}
STC_DEF size_t
cstr_find_n(cstr_t s, const char* needle, size_t pos, size_t nlen) {
- if (pos > cstr_size(s)) return cstr_npos;
+ if (pos > _cstr_rep(&s)->size) return cstr_npos;
char* res = c_strnfind(s.str + pos, needle, nlen);
return res ? res - s.str : cstr_npos;
}
STC_DEF size_t
cstr_ifind_n(cstr_t s, const char* needle, size_t pos, size_t nlen) {
- if (pos > cstr_size(s)) return cstr_npos;
+ if (pos > _cstr_rep(&s)->size) return cstr_npos;
char* res = c_istrnfind(s.str + pos, needle, nlen);
return res ? res - s.str : cstr_npos;
}