summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-12-14 22:28:45 +0100
committerTyge Løvset <[email protected]>2021-12-14 22:28:45 +0100
commitfb8b06d933510add5f530d265a687899828d4904 (patch)
tree40f18361dbb1ca5a0d17be59a2d60b9f5c1b0caf
parent9b83dd92e4ea590406ded5276b44cd83b4cf3b86 (diff)
downloadSTC-modified-fb8b06d933510add5f530d265a687899828d4904.tar.gz
STC-modified-fb8b06d933510add5f530d265a687899828d4904.zip
Some more docs updates and new csptr examples.
-rw-r--r--README.md6
-rw-r--r--docs/cbox_api.md18
-rw-r--r--docs/ccommon_api.md2
-rw-r--r--examples/sptr_erase.c52
-rw-r--r--examples/sptr_to_maps.c75
5 files changed, 141 insertions, 12 deletions
diff --git a/README.md b/README.md
index 78043037..452cc245 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@ STC - Smart Template Containers for C
News
----
- Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`.
-- Added **cbox** type: container of one element: similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr)
-- Replaced example for **csptr** in docs.
-- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structural binding" as in c++.
+- Added [**cbox**](docs/cbox_api.md) type: container of one element, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr)
+- Added [example for **csptr**](examples/sptr_to_maps.c).
+- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding".
- Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*.
- Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*.
- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_ref` / `i_val_ref` when specifying containers with **csptr** or **cbox** elements.
diff --git a/docs/cbox_api.md b/docs/cbox_api.md
index 1f10928d..83cec830 100644
--- a/docs/cbox_api.md
+++ b/docs/cbox_api.md
@@ -1,15 +1,17 @@
-# STC [cbox](../include/stc/cbox.h): Shared Pointers
+# STC [cbox](../include/stc/cbox.h): (Boxed) Heap Allocated Objects
-**cbox** is a container for one heap allocated object. A **cbox** is empty by default.
-The *cbox_X_compare()*, *cbox_X_del()* methods are defined based on the `i_cmp`
-and `i_valdel` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which
-uses the `i_valfrom` macro if defined.
+**cbox** is a A box is a smart pointer to a heap allocated value of type X. A **cbox** can
+be empty. The *cbox_X_compare()*, *cbox_X_del()* methods are defined based on the `i_cmp`
+and `i_valdel` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the
+`i_valfrom` macro if defined.
-When declaring a container with cbox elements, define `i_val_ref` as the cbox type, see example.
+When declaring a container of **cbox** values, it is recommended to define `i_val_ref` to the
+cbox type instead of defining `i_val`. This will auto-set `i_del`, `i_from`, and `i_cmp` using
+functions defined by the specified **cbox**.
For containers, make sure to pass the result of create functions like *cbox_X_new()* **only** to
-*insert()*, *push_back()*, and *push()* functions. Use *emplace()* functions to deep clone
-already existing/owned cbox elements.
+*insert()*, *push_back()*, and *push()* functions. Use the *emplace()* functions in order to
+auto-*clone* an already existing/owned cbox element.
See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) for a functional reference, or Rust [std::boxed::Box](https://doc.rust-lang.org/std/boxed/struct.Box.html)
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 4dc099fb..12609eeb 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -85,7 +85,7 @@ int main()
|:-------------------------------------------|:--------------------------------|
| `c_foreach (it, ctype, container)` | Iteratate all elements |
| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
-| `c_forpair (key, value, ctype, container)` | Iterate with structural binding |
+| `c_forpair (key, value, ctype, container)` | Iterate with structured binding |
```c
#define i_key int
diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c
new file mode 100644
index 00000000..eada6fd6
--- /dev/null
+++ b/examples/sptr_erase.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+
+void show_del(int* x) { printf("del: %d\n", *x); }
+
+#define i_val int
+#define i_del show_del // this "destroy" func shows which elements are destroyed
+// csptr/cbox will try to use default comparison of i_val (int) if no cmp func is specified,
+// unless 'i_opt c_no_compare' is defined, in which case pointer addresses are compared.
+// See the different results by commenting in the next line.
+//#define i_opt c_no_compare
+#include <stc/csptr.h> // csptr_int: shared pointer to int
+
+#define i_val_ref csptr_int
+#define i_tag intp
+#include <stc/cvec.h> // cvec_intp: cvec<csptr_int>
+
+
+int main()
+{
+ c_auto (cvec_intp, vec)
+ {
+ const int v[] = {2012, 1990, 2012, 2019, 2015};
+ c_forrange (i, c_arraylen(v))
+ cvec_intp_push_back(&vec, csptr_int_new(v[i]));
+
+ // clone the second 2012 and push it back.
+ // note: cloning make sure that vec.data[2] has ref count 2.
+ cvec_intp_emplace_back(&vec, vec.data[2]);
+
+ printf("vec before erase :");
+ c_foreach (i, cvec_intp, vec)
+ printf(" %d", *i.ref->get);
+ puts("");
+
+ // erase vec.data[2]; or first matching value depending on compare.
+ cvec_intp_iter it;
+ it = cvec_intp_find(&vec, vec.data[2]);
+ if (it.ref != cvec_intp_end(&vec).ref)
+ cvec_intp_erase_at(&vec, it);
+
+ int year = 2015;
+ it = cvec_intp_find(&vec, (csptr_int){&year}); // Ok as tmp only.
+ if (it.ref != cvec_intp_end(&vec).ref)
+ cvec_intp_erase_at(&vec, it);
+
+ printf("vec after erase :");
+ c_foreach (i, cvec_intp, vec)
+ printf(" %d", *i.ref->get);
+
+ puts("\nDone");
+ }
+}
diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c
new file mode 100644
index 00000000..77871304
--- /dev/null
+++ b/examples/sptr_to_maps.c
@@ -0,0 +1,75 @@
+// Create a stack and a list of shared pointers to maps,
+// and demonstrate sharing and cloning of maps.
+#define i_type Map
+#define i_key_str // strings
+#define i_val int
+#define i_keydel(p) (printf("del name: %s\n", (p)->str), cstr_del(p))
+#include <stc/csmap.h>
+
+#define i_type Arc // (atomic) ref. counted type
+#define i_val Map
+#define i_del(p) (printf("del Arc:\n"), Map_del(p))
+// no comparison of Maps needed (or available), and
+// no need for atomic ref. count in single thread:
+#define i_opt c_no_compare|c_no_atomic
+#include <stc/csptr.h>
+
+#define i_type Stack
+#define i_val_ref Arc // define i_val_ref for csptr/cbox value (not i_val)
+#include <stc/cstack.h>
+
+#define i_type List
+#define i_val_ref Arc // as above
+#include <stc/clist.h>
+
+int main()
+{
+ c_auto (Stack, stack)
+ c_auto (List, list)
+ {
+ // POPULATE stack with shared pointers to Maps:
+ Map *map;
+ map = Stack_push(&stack, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992}
+ });
+ map = Stack_push(&stack, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980}
+ });
+
+ // POPULATE list:
+ map = List_push_back(&list, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003}
+ });
+
+ // Share two Maps from the stack with the list using emplace (clone the csptr):
+ List_emplace_back(&list, stack.data[0]);
+ List_emplace_back(&list, stack.data[1]);
+
+ // Clone (deep copy) a Map from the stack to the list
+ // List will contain two shared and two unshared maps.
+ map = List_push_back(&list, Arc_new(Map_clone(*stack.data[1].get)))->get;
+
+ // Add one more element to the cloned map:
+ Map_emplace_or_assign(map, "CLONED", 2021);
+
+ // Add one more element to the shared map:
+ Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021);
+
+
+ puts("STACKS");
+ c_foreach (i, Stack, stack) {
+ c_forpair (name, year, Map, *i.ref->get)
+ printf(" %s:%d", _.name.str, _.year);
+ puts("");
+ }
+ puts("LIST");
+ c_foreach (i, List, list) {
+ c_forpair (name, year, Map, *i.ref->get)
+ printf(" %s:%d", _.name.str, _.year);
+ puts("");
+ }
+ }
+}