diff options
| -rw-r--r-- | benchmarks/others/csmap_v1.h (renamed from examples/csmap_v1.h) | 4 | ||||
| -rw-r--r-- | docs/cmap_api.md | 6 | ||||
| -rw-r--r-- | docs/csmap_api.md | 9 | ||||
| -rw-r--r-- | docs/cstr_api.md | 22 | ||||
| -rw-r--r-- | examples/mapmap.c | 22 | ||||
| -rw-r--r-- | examples/read.c | 27 | ||||
| -rw-r--r-- | stc/csmap.h | 25 | ||||
| -rw-r--r-- | stc/cstr.h | 19 | ||||
| -rw-r--r-- | stc/cvec.h | 2 |
9 files changed, 106 insertions, 30 deletions
diff --git a/examples/csmap_v1.h b/benchmarks/others/csmap_v1.h index ec63c021..b81d7554 100644 --- a/examples/csmap_v1.h +++ b/benchmarks/others/csmap_v1.h @@ -385,11 +385,11 @@ int main(void) { while (it->level) { \
up[top++] = it; \
C##X##_rawkey_t r = keyToRaw(KEY_REF_##C(&it->value)); \
- if ((c = keyCompareRaw(&r, rkey)) == 0) {res->first = &it->value; return tn;} \
+ if ((c = keyCompareRaw(&r, rkey)) == 0) {res->ref = &it->value; return tn;} \
it = it->link[(dir = (c == -1))]; \
} \
tn = c_new_1(C##X##_node_t); \
- res->first = &tn->value, res->second = true; \
+ res->ref = &tn->value, res->inserted = true; \
tn->link[0] = tn->link[1] = (C##X##_node_t*) &aatree_nil, tn->level = 1; \
if (top == 0) return tn; \
up[top - 1]->link[dir] = tn; \
diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 371129c1..593f78ab 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -61,16 +61,16 @@ size_t cmap_X_bucket_count(cmap_X map); cmap_X_iter_t cmap_X_find(const cmap_X* self, RawKey rkey); bool cmap_X_contains(const cmap_X* self, RawKey rkey); +cmap_X_mapped_t* cmap_X_at(const cmap_X* self, RawKey rkey); // rkey must be in map. cmap_X_result_t cmap_X_insert(cmap_X* self, Key key, Mapped mapped); // no change if key in map cmap_X_result_t cmap_X_insert_or_assign(cmap_X* self, Key key, Mapped mapped); // always update mapped -cmap_X_result_t cmap_X_put(cmap_X* self, RawKey rkey, RawMapped rmapped); // alias for insert_or_assign +cmap_X_result_t cmap_X_put(cmap_X* self, Key key, Mapped mapped); // alias for insert_or_assign + cmap_X_result_t cmap_X_emplace(cmap_X* self, RawKey rkey, RawMapped rmapped); // no change if rkey in map cmap_X_result_t cmap_X_emplace_or_assign(cmap_X* self, RawKey rkey, RawMapped rmapped); // always update rmapped void cmap_X_emplace_n(cmap_X* self, const cmap_X_rawvalue_t arr[], size_t size); -cmap_X_mapped_t* cmap_X_at(const cmap_X* self, RawKey rkey); // rkey must be in map. - size_t cmap_X_erase(cmap_X* self, RawKey rkey); cmap_X_iter_t cmap_X_erase_at(cmap_X* self, cmap_X_iter_t pos); void cmap_X_erase_entry(cmap_X* self, cmap_X_value_t* entry); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 72688c26..4b8f058a 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -55,18 +55,19 @@ bool csmap_X_empty(csmap_X map); size_t csmap_X_size(csmap_X map); csmap_X_iter_t csmap_X_find(const csmap_X* self, RawKey rkey); -csmap_X_value_t* csmap_X_find_it(const csmap_X* self, RawKey rkey, csmap_X_iter_t* out); // return NULL if not found +csmap_X_iter_t csmap_X_lower_bound(const csmap_X* self, RawKey rkey); // find closest entry >= rkey bool csmap_X_contains(const csmap_X* self, RawKey rkey); +csmap_X_value_t* csmap_X_find_it(const csmap_X* self, RawKey rkey, csmap_X_iter_t* out); // return NULL if not found +csmap_X_mapped_t* csmap_X_at(const csmap_X* self, RawKey rkey); // rkey must be in map. csmap_X_result_t csmap_X_insert(csmap_X* self, Key key, Mapped mapped); // no change if key in map csmap_X_result_t csmap_X_insert_or_assign(csmap_X* self, Key key, Mapped mapped); // always update mapped -csmap_X_result_t csmap_X_put(csmap_X* self, RawKey rkey, RawMapped rmapped); // alias for insert_or_assign +csmap_X_result_t csmap_X_put(csmap_X* self, Key key, Mapped mapped); // alias for insert_or_assign + csmap_X_result_t csmap_X_emplace(csmap_X* self, RawKey rkey, RawMapped rmapped); // no change if rkey in map csmap_X_result_t csmap_X_emplace_or_assign(csmap_X* self, RawKey rkey, RawMapped rmapped); // always update rmapped void csmap_X_emplace_n(csmap_X* self, const csmap_X_rawvalue_t arr[], size_t size); -csmap_X_mapped_t* csmap_X_at(const csmap_X* self, RawKey rkey); // rkey must be in map. - size_t csmap_X_erase(csmap_X* self, RawKey rkey); csmap_X_iter_t csmap_X_erase_at(csmap_X* self, csmap_X_iter_t pos); diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 9f26187b..e528aafb 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -23,6 +23,8 @@ cstr cstr_from_n(const char* str, size_t n); cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting cstr cstr_clone(cstr s); +cstr* cstr_take(cstr* self, cstr s); // take the constructed or moved string +cstr cstr_move(cstr* self); // move string to caller, leave empty string void cstr_del(cstr *self); // destructor size_t cstr_size(cstr s); @@ -33,22 +35,26 @@ bool cstr_empty(cstr s); size_t cstr_reserve(cstr* self, size_t capacity); void cstr_resize(cstr* self, size_t len, char fill); void cstr_clear(cstr* self); + cstr* cstr_assign(cstr* self, const char* str); +cstr* cstr_assign_s(cstr* self, cstr s); cstr* cstr_assign_n(cstr* self, const char* str, size_t n); -cstr* cstr_take(cstr* self, cstr s); // take the constructed or moved string -cstr cstr_move(cstr* self); // move string to caller, leave empty string cstr* cstr_append(cstr* self, const char* str); -cstr* cstr_append_n(cstr* self, const char* str, size_t n); // appends len characters -void cstr_push_back(cstr* self, char ch); -void cstr_pop_back(cstr* self); +cstr* cstr_append_s(cstr* self, cstr s); +cstr* cstr_append_n(cstr* self, const char* str, size_t n); // appends len characters + void cstr_insert(cstr* self, size_t pos, const char* str); +void cstr_insert_s(cstr* self, size_t pos, cstr s); void cstr_insert_n(cstr* self, size_t pos, const char* str, size_t n); -void cstr_erase(cstr* self, size_t pos); -void cstr_erase_n(cstr* self, size_t pos, size_t n); + void cstr_replace(cstr* self, size_t pos, size_t len, const char* str); +void cstr_replace_s(cstr* self, size_t pos, size_t len, cstr s); void cstr_replace_n(cstr* self, size_t pos, size_t len, const char* str, size_t n); +void cstr_erase(cstr* self, size_t pos); +void cstr_erase_n(cstr* self, size_t pos, size_t n); + int cstr_compare(const cstr *s1, const cstr *s2); bool cstr_equals(cstr s, const char* str); bool cstr_equals_s(cstr s, cstr s2); @@ -63,6 +69,8 @@ bool cstr_ibegins_with(cstr s, const char* substr); bool cstr_ends_with(cstr s, const char* substr); bool cstr_iends_with(cstr s, const char* substr); +void cstr_push_back(cstr* self, char ch); +void cstr_pop_back(cstr* self); char* cstr_front(cstr* self); char* cstr_back(cstr* self); diff --git a/examples/mapmap.c b/examples/mapmap.c index e22ac80c..fc6c8a79 100644 --- a/examples/mapmap.c +++ b/examples/mapmap.c @@ -3,24 +3,26 @@ #include <stc/cmap.h>
#include <stc/cstr.h>
+// unordered_map<string, unordered_map<string, string>>:
+
using_cmap_str();
using_cmap_strkey(cfg, cmap_str, cmap_str_del, c_no_clone);
int main(void) {
- cmap_cfg config = cmap_cfg_init();
+ cmap_cfg cfg = cmap_cfg_init();
cmap_str init = cmap_str_init();
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("user"), init).ref->second, "name", "Joe");
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("user"), init).ref->second, "groups", "proj1,proj3");
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("group"), init).ref->second, "proj1", "Energy");
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("group"), init).ref->second, "proj2", "Windy");
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("group"), init).ref->second, "proj3", "Oil");
- cmap_str_emplace(&cmap_cfg_insert(&config, cstr_from("admin"), init).ref->second, "employees", "2302");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("user"), init).ref->second, "name", "Joe");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("user"), init).ref->second, "groups", "proj1,proj3");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("group"), init).ref->second, "proj1", "Energy");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("group"), init).ref->second, "proj2", "Windy");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("group"), init).ref->second, "proj3", "Oil");
+ cmap_str_emplace(&cmap_cfg_insert(&cfg, cstr_from("admin"), init).ref->second, "employees", "2302");
- cmap_str_emplace_or_assign(&cmap_cfg_insert(&config, cstr_from("group"), init).ref->second, "proj2", "Wind"); // Update
+ cmap_str_emplace_or_assign(&cmap_cfg_insert(&cfg, cstr_from("group"), init).ref->second, "proj2", "Wind"); // Update
- c_foreach (i, cmap_cfg, config)
+ c_foreach (i, cmap_cfg, cfg)
c_foreach (j, cmap_str, i.ref->second)
printf("%s: %s - %s (%u)\n", i.ref->first.str, j.ref->first.str, j.ref->second.str, i.ref->second.bucket_count);
- cmap_cfg_del(&config);
+ cmap_cfg_del(&cfg);
}
\ No newline at end of file diff --git a/examples/read.c b/examples/read.c new file mode 100644 index 00000000..b3ddcc00 --- /dev/null +++ b/examples/read.c @@ -0,0 +1,27 @@ +#include <errno.h>
+#include <stc/cstr.h>
+#include <stc/cvec.h>
+
+using_cvec_str();
+
+cvec_str read_file(const char* name) {
+ cvec_str vec = cvec_str_init();
+ c_withfile (f, fopen(name, "r")) {
+ cstr line = cstr_init();
+ while (cstr_getline(&line, f))
+ cvec_str_emplace_back(&vec, line.str);
+ cstr_del(&line);
+ }
+ return vec;
+}
+
+int main() {
+ cvec_str vec = read_file("read.c");
+ if (errno) printf("errno: %d\n", errno);
+
+ int n = 0;
+ c_foreach (i, cvec_str, vec)
+ printf("%5d: %s\n", ++n, i.ref->str);
+
+ cvec_str_del(&vec);
+}
\ No newline at end of file diff --git a/stc/csmap.h b/stc/csmap.h index e2cc6fcf..05ba949b 100644 --- a/stc/csmap.h +++ b/stc/csmap.h @@ -229,12 +229,16 @@ struct csmap_rep { size_t root, disp, head, size, cap; void* nodes[]; }; STC_API C##X##_value_t* \
C##X##_find_it(const C##X* self, RawKey rkey, C##X##_iter_t* out); \
\
+ STC_API C##X##_iter_t \
+ C##X##_lower_bound(const C##X* self, RawKey rkey); \
+\
STC_INLINE C##X##_iter_t \
C##X##_find(const C##X* self, RawKey rkey) { \
C##X##_iter_t it; \
C##X##_find_it(self, rkey, &it); \
return it; \
} \
+\
STC_INLINE bool \
C##X##_contains(const C##X* self, RawKey rkey) { \
C##X##_iter_t it; \
@@ -387,13 +391,28 @@ static struct csmap_rep _smap_inits = {0, 0, 0, 0}; out->_top = 0; \
while (tn) { \
int c; C##X##_rawkey_t rx = keyToRaw(KEY_REF_##C(&d[tn].value)); \
- if ((c = keyCompareRaw(&rx, &rkey)) < 0) tn = d[tn].link[1]; \
- else if (c > 0) {out->_st[out->_top++] = tn; tn = d[tn].link[0];} \
- else {out->_tn = d[tn].link[1]; return (out->ref = &d[tn].value);} \
+ if ((c = keyCompareRaw(&rx, &rkey)) < 0) \
+ tn = d[tn].link[1]; \
+ else if (c > 0) \
+ { out->_st[out->_top++] = tn; tn = d[tn].link[0]; } \
+ else \
+ { out->_tn = d[tn].link[1]; return (out->ref = &d[tn].value); } \
} \
return (out->ref = NULL); \
} \
\
+ STC_DEF C##X##_iter_t \
+ C##X##_lower_bound(const C##X* self, RawKey rkey) { \
+ C##X##_iter_t it; \
+ C##X##_find_it(self, rkey, &it); \
+ if (!it.ref && it._top) { \
+ C##X##_size_t tn = it._st[--it._top]; \
+ it._tn = it._d[tn].link[1]; \
+ it.ref = &it._d[tn].value; \
+ } \
+ return it; \
+ } \
+\
STC_DEF void \
C##X##_next(C##X##_iter_t *it) { \
C##X##_size_t tn = it->_tn; \
@@ -116,6 +116,10 @@ STC_INLINE cstr_t* cstr_assign(cstr_t* self, const char* str) {
return cstr_assign_n(self, str, strlen(str));
}
+STC_INLINE cstr_t*
+cstr_assign_s(cstr_t* self, cstr s) {
+ return cstr_assign_n(self, s.str, _cstr_rep(&s)->size);
+}
STC_INLINE cstr_t*
cstr_take(cstr_t* self, cstr_t s) {
@@ -135,6 +139,11 @@ STC_INLINE cstr_t* cstr_append(cstr_t* self, const char* str) {
return cstr_append_n(self, str, strlen(str));
}
+STC_INLINE cstr_t*
+cstr_append_s(cstr_t* self, cstr s) {
+ return cstr_append_n(self, s.str, _cstr_rep(&s)->size);
+}
+
STC_INLINE void
cstr_push_back(cstr_t* self, char value) {
cstr_append_n(self, &value, 1);
@@ -153,10 +162,20 @@ cstr_insert(cstr_t* self, size_t pos, const char* str) { cstr_replace_n(self, pos, 0, str, strlen(str));
}
STC_INLINE void
+cstr_insert_s(cstr_t* self, size_t pos, cstr s) {
+ cstr_replace_n(self, pos, 0, s.str, _cstr_rep(&s)->size);
+}
+
+STC_INLINE void
cstr_replace(cstr_t* self, size_t pos, size_t len, const char* str) {
cstr_replace_n(self, pos, len, str, strlen(str));
}
STC_INLINE void
+cstr_replace_s(cstr_t* self, size_t pos, size_t len, cstr s) {
+ cstr_replace_n(self, pos, len, s.str, _cstr_rep(&s)->size);
+}
+
+STC_INLINE void
cstr_erase(cstr_t* self, size_t pos) {cstr_erase_n(self, pos, 1);}
STC_INLINE bool
@@ -73,7 +73,7 @@ typedef int (*c_cmp_fn)(const void*, const void*); STC_API void \
cvec_##X##_resize(cvec_##X* self, size_t size, Value fill_val); \
STC_INLINE void \
- cvec_##X##_swap(cvec_##X* a, cvec_##X* b) {c_swap(cvec_##X##_value_t*, a->data, b->data);} \
+ cvec_##X##_swap(cvec_##X* a, cvec_##X* b) {c_swap(cvec_##X, *a, *b);} \
\
STC_INLINE cvec_##X \
cvec_##X##_with_size(size_t size, Value null_val) { \
|
