Skip to content

Commit 52736e0

Browse files
Merge pull request #6 from mongodb-labs/feature/crud-tut
[CDRIVER-5662] Tutorials for simple CRUD, and some more convience APIs
2 parents 9c54173 + 8c40a59 commit 52736e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1619
-307
lines changed

.clang-format

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ IncludeCategories:
8282
InsertNewlineAtEOF: true
8383
IfMacros:
8484
- mlib_math_catch
85+
- amongoc_if_error
86+
ForEachMacros:
87+
- bson_foreach
8588
AllowBreakBeforeNoexceptSpecifier: Always
8689
---
8790
# For some reason, Clang sees some files as Objective-C. Add this section just to appease it.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ build:
3535
test: build
3636
cmake -E chdir "$(BUILD_DIR)" ctest -C "$(CONFIG)" --output-on-failure -j8
3737

38-
all_sources := $(shell find $(THIS_DIR)/src/ $(THIS_DIR)/include/ $(THIS_DIR)/tests/ -name '*.c' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp')
38+
all_sources := $(shell find $(THIS_DIR)/src/ $(THIS_DIR)/include/ $(THIS_DIR)/tests/ $(THIS_DIR)/docs/ -name '*.c' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp')
3939
format-check: poetry-install
4040
$(POETRY) run python tools/include-fixup.py --check
4141
$(POETRY) run $(MAKE) _format-check

docs/conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def generate_sphinx_inventory(
229229
.. |static| replace:: :cpp:`static`
230230
.. |const| replace:: :cpp:`const`
231231
.. |void| replace:: :cpp:`void`
232+
.. |char| replace:: :cpp:`char`
232233
.. |A| replace:: :math:`A`
233234
.. |A'| replace:: :math:`A'`
234235
.. |B| replace:: :math:`B`
@@ -337,6 +338,7 @@ def merge_domaindata(self, docnames: list[str], otherdata: dict[str, Any]) -> No
337338
"default_loop",
338339
"client",
339340
"collection",
341+
"cursor",
340342
)
341343
),
342344
*(
@@ -414,6 +416,8 @@ class CustomCppLexer(CppLexer):
414416
(r"bson_type_\w+\b", token.Name.Constant),
415417
# Other macro
416418
(r"bson_foreach\w*\b", token.Keyword),
419+
(r"amongoc_declmsg\b", token.Keyword),
420+
(r"amongoc_if_error\b", token.Keyword),
417421
inherit,
418422
],
419423
}

docs/how-to/communicate.example.c

Lines changed: 13 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
#include <amongoc/amongoc.h>
22

3-
#include "bson/view.h"
3+
#include <bson/format.h>
44
#include <bson/iterator.h>
55
#include <bson/mut.h>
6-
7-
#include "mlib/str.h"
6+
#include <bson/view.h>
87

98
/**
109
* @brief Shared state for the application. This is passed through the app as pointer stored
@@ -15,11 +14,6 @@ typedef struct app_state {
1514
amongoc_client* client;
1615
} app_state;
1716

18-
/**
19-
* @brief Write the content of a BSON document in JSON-like format to the given output
20-
*/
21-
static void print_bson(FILE* into, bson_view doc, mlib_str_view indent);
22-
2317
/** after_hello()
2418
* @brief Handle the `hello` response from the server
2519
*
@@ -32,7 +26,7 @@ amongoc_box after_hello(amongoc_box state_ptr, amongoc_status*, amongoc_box resp
3226
bson_view resp = bson_view_from(amongoc_box_cast(bson_doc, resp_data));
3327
// Just print the response message
3428
fprintf(stdout, "Got response: ");
35-
print_bson(stdout, resp, mlib_str_view_from(""));
29+
bson_write_repr(stdout, resp);
3630
fputs("\n", stdout);
3731
amongoc_box_destroy(resp_data);
3832
return amongoc_nil;
@@ -72,8 +66,12 @@ int main(int argc, char const* const* argv) {
7266
}
7367
const char* const uri = argv[1];
7468

75-
amongoc_loop loop;
76-
amongoc_default_loop_init(&loop);
69+
amongoc_loop loop;
70+
amongoc_status status = amongoc_default_loop_init(&loop);
71+
amongoc_if_error (status, msg) {
72+
fprintf(stderr, "Error setting up the event loop: %s\n", msg);
73+
return 2;
74+
}
7775

7876
struct app_state state = {0};
7977

@@ -88,8 +86,7 @@ int main(int argc, char const* const* argv) {
8886
amongoc_box_pointer(&state),
8987
after_connect_say_hello);
9088

91-
amongoc_status fin_status = amongoc_okay;
92-
amongoc_operation op = amongoc_tie(em, &fin_status, NULL, mlib_default_allocator);
89+
amongoc_operation op = amongoc_tie(em, &status);
9390
amongoc_start(&op);
9491
amongoc_default_loop_run(&loop);
9592
amongoc_operation_delete(op);
@@ -98,71 +95,13 @@ int main(int argc, char const* const* argv) {
9895
amongoc_client_delete(state.client);
9996
amongoc_default_loop_destroy(&loop);
10097

101-
if (amongoc_is_error(fin_status)) {
102-
char* m = amongoc_status_strdup_message(fin_status);
103-
fprintf(stderr, "An error occurred: %s\n", m);
104-
free(m);
98+
// Final status
99+
amongoc_if_error (status, msg) {
100+
fprintf(stderr, "An error occurred: %s\n", msg);
105101
return 2;
106102
} else {
107103
printf("Okay\n");
108104
return 0;
109105
}
110106
}
111107
// end.
112-
113-
static void print_bson(FILE* into, bson_view doc, mlib_str_view indent) {
114-
fprintf(into, "{\n");
115-
bson_foreach(it, doc) {
116-
mlib_str_view str = bson_key(it);
117-
fprintf(into, "%*s \"%s\": ", (int)indent.len, indent.data, str.data);
118-
bson_value_ref val = bson_iterator_value(it);
119-
switch (val.type) {
120-
case bson_type_eod:
121-
case bson_type_double:
122-
fprintf(into, "%f,\n", val.double_);
123-
break;
124-
case bson_type_utf8:
125-
fprintf(into, "\"%s\",\n", val.utf8.data);
126-
break;
127-
case bson_type_document:
128-
case bson_type_array: {
129-
mlib_str i2 = mlib_str_append(indent, " ");
130-
bson_view subdoc = bson_iterator_value(it).document;
131-
print_bson(into, subdoc, mlib_str_view_from(i2));
132-
mlib_str_delete(i2);
133-
fprintf(into, ",\n");
134-
break;
135-
}
136-
case bson_type_undefined:
137-
fprintf(into, "[undefined],\n");
138-
break;
139-
case bson_type_bool:
140-
fprintf(into, val.bool_ ? "true,\n" : "false,\n");
141-
break;
142-
case bson_type_null:
143-
fprintf(into, "null,\n");
144-
break;
145-
case bson_type_int32:
146-
fprintf(into, "%d,\n", val.int32);
147-
break;
148-
case bson_type_int64:
149-
fprintf(into, "%ld,\n", val.int64);
150-
break;
151-
case bson_type_timestamp:
152-
case bson_type_decimal128:
153-
case bson_type_maxkey:
154-
case bson_type_minkey:
155-
case bson_type_oid:
156-
case bson_type_binary:
157-
case bson_type_datetime:
158-
case bson_type_regex:
159-
case bson_type_dbpointer:
160-
case bson_type_code:
161-
case bson_type_symbol:
162-
case bson_type_codewscope:
163-
fprintf(into, "[[printing unimplemented for this type]],\n");
164-
break;
165-
}
166-
}
167-
fprintf(into, "%*s}", (int)indent.len, indent.data);
168-
}

docs/how-to/communicate.rst

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The first "interesting" code will declare and initialize the default event loop:
4646
.. literalinclude:: communicate.example.c
4747
:lineno-match:
4848
:start-at: loop;
49-
:end-at: );
49+
:end-at: }
5050

5151
.. seealso:: `amongoc_loop` and `amongoc_default_loop_init`
5252

@@ -204,14 +204,11 @@ the first continuation, we use `amongoc_tie` to convert the emitter to an
204204

205205
.. literalinclude:: communicate.example.c
206206
:lineno-match:
207-
:start-at: fin_status
207+
:start-at: amongoc_tie
208208
:end-at: amongoc_tie
209209

210210
This will allow us to see the final result status of the program in
211-
``fin_status`` after the returned operation ``op`` completes. We pass ``NULL``
212-
for the `amongoc_tie::value` parameter, indicating that we do not care what the
213-
final result value will be (in a successful case, this would just be the
214-
`amongoc_nil` returned from ``after_hello``).
211+
``fin_status`` after the returned operation ``op`` completes.
215212

216213

217214
Start the Operation, Run the Loop, and Clean Up
@@ -243,7 +240,7 @@ Print the Final Result
243240

244241
.. literalinclude:: communicate.example.c
245242
:lineno-match:
246-
:start-at: is_error
243+
:start-at: // Final status
247244
:end-before: end.
248245

249246
Finally, we inspect the `amongoc_status` that was produced by our operation and

docs/how-to/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ How-to Guides
66
:caption: Guides
77
:maxdepth: 2
88

9+
status-handling
910
communicate
1011
looping

docs/how-to/looping.example.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ typedef struct {
2020
*
2121
* @param state_ptr Pointer to the `state` for the program
2222
*/
23-
amongoc_emitter loop_step(amongoc_box state_ptr, amongoc_status prev_status, amongoc_box prev_res) {
23+
amongoc_emitter loop_step(amongoc_box state_ptr, //
24+
amongoc_status prev_status,
25+
amongoc_box prev_res) {
2426
(void)prev_res;
2527
(void)prev_status;
2628
// Print our status
@@ -60,7 +62,10 @@ int main(int argc, char const* const* argv) {
6062

6163
// Create a default loop
6264
amongoc_loop loop;
63-
amongoc_default_loop_init(&loop);
65+
amongoc_if_error (amongoc_default_loop_init(&loop), msg) {
66+
fprintf(stderr, "Error initializing event loop: %s\n", msg);
67+
return 1;
68+
}
6469

6570
// Seed the initial sum
6671
state app_state = {.countdown = delay, .loop = &loop, .a = 0, .b = 1};
@@ -70,22 +75,19 @@ int main(int argc, char const* const* argv) {
7075
// Tie the final result for later, and start the program
7176
amongoc_status status;
7277
amongoc_box result;
73-
amongoc_operation op = amongoc_tie(em, &status, &result, mlib_default_allocator);
78+
amongoc_operation op = amongoc_tie(em, &status, &result);
7479
amongoc_start(&op);
7580
// Run the program within the event loop
7681
amongoc_default_loop_run(&loop);
7782
amongoc_operation_delete(op);
7883
amongoc_default_loop_destroy(&loop);
7984

80-
if (amongoc_is_error(status)) {
81-
char* msg = amongoc_status_strdup_message(status);
85+
amongoc_if_error (status, msg) {
8286
fprintf(stderr, "error: %s\n", msg);
83-
free(msg);
8487
amongoc_box_destroy(result);
8588
return 2;
86-
} else {
87-
// Get the value returned with `amongoc_just` in `loop_step`
88-
printf("Got final value: %lu\n", amongoc_box_cast(uint64_t, result));
8989
}
90+
// Get the value returned with `amongoc_just` in `loop_step`
91+
printf("Got final value: %lu\n", amongoc_box_cast(uint64_t, result));
9092
return 0;
9193
}

docs/how-to/looping.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,14 @@ program. We check for errors, either printing the error message or printing the
196196
final result:
197197

198198
.. literalinclude:: looping.example.c
199-
:start-at: is_error
199+
:start-at: if_error (status, msg)
200200
:end-at: return 0;
201201
:lineno-match:
202202

203-
We use `amongoc_is_error` to test the final status for an error condition. If it
204-
is an error, we get and print the error message to stderr, and we must destroy
205-
the final result box because it may contain an unspecified value related to the
206-
error, but we don't want to do anything with it.
203+
We use :c:macro:`amongoc_if_error` to test the final status for an error
204+
condition. If it is an error, we get and print the error message to stderr, and
205+
we must destroy the final result box because it may contain an unspecified value
206+
related to the error, but we don't want to do anything with it.
207207

208208
In the success case, we extract the value returned in `amongoc_just` as a
209209
``uint64_t`` and print it to stdout. Note that because the box returned by

0 commit comments

Comments
 (0)