complete the printf documentation and fix code formatting

Sat, 15 Feb 2025 17:43:21 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 15 Feb 2025 17:43:21 +0100
changeset 1210
2ad0cf0f314b
parent 1209
4a72c47226f4
child 1211
37cfb534800e

complete the printf documentation and fix code formatting

relates to #451

docs/Writerside/topics/allocator.h.md file | annotate | diff | comparison | revisions
docs/Writerside/topics/memory.md file | annotate | diff | comparison | revisions
docs/Writerside/topics/printf.h.md file | annotate | diff | comparison | revisions
docs/Writerside/topics/streams.h.md file | annotate | diff | comparison | revisions
--- a/docs/Writerside/topics/allocator.h.md	Sat Feb 15 16:36:29 2025 +0100
+++ b/docs/Writerside/topics/allocator.h.md	Sat Feb 15 17:43:21 2025 +0100
@@ -17,17 +17,17 @@
 void *cxMalloc(const CxAllocator *allocator, size_t n);
 
 void *cxCalloc(const CxAllocator *allocator,
-               size_t nmemb, size_t size);
+        size_t nmemb, size_t size);
 
 void *cxRealloc(const CxAllocator *allocator, void *mem, size_t n);
 
 void *cxReallocArray(const CxAllocator *allocator, void *mem,
-                     size_t nmemb, size_t size);
+        size_t nmemb, size_t size);
 
 int cxReallocate(const CxAllocator *allocator, void **mem, size_t n);
 
 int cxReallocateArray(const CxAllocator *allocator, void **mem,
-                      size_t nmemb, size_t size);
+        size_t nmemb, size_t size);
     
 void cxFree(const CxAllocator *allocator, void *mem);
 
@@ -124,21 +124,21 @@
 and the second one is called _advanced_ destructor.
 The only difference is that you can pass additional custom `data` to an advanced destructor function.
 
-Destructor functions play a vital role in deep de-allocations.
-Another scenarios, besides destroying elements in a collection, are the de-allocation of objects
-stored in a [memory pool](mempool.h.md) or de-allocations of deeply nested [JSON](json.h.md) objects.
+Destructor functions play a vital role in deep deallocations.
+Another scenarios, besides destroying elements in a collection, are the deallocation of objects
+stored in a [memory pool](mempool.h.md) or deallocations of deeply nested [JSON](json.h.md) objects.
 
 > Destructor functions are not to be confused with `free()`-like functions.
 > The fundamental differences are that 
 > * it is not safe to pass `NULL` to a destructor function
-> * a destructor may only de-allocate the contents inside an object but not the object itself, depending on context
+> * a destructor may only deallocate the contents inside an object but not the object itself, depending on context
 >
 {style="note"}
 
 > For example, when you are using a [list](list.h.md) that stores elements directly, a destructor function
 > assigned to that collection may only destroy the element's contents but must not deallocate the element's memory.
 > On the other hand, when the list is storing just pointers to the elements, you _may_ want the destructor
-> function to also de-allocate the element's memory when the element is removed from that list.
+> function to also deallocate the element's memory when the element is removed from that list.
 
 <seealso>
 <category ref="apidoc">
--- a/docs/Writerside/topics/memory.md	Sat Feb 15 16:36:29 2025 +0100
+++ b/docs/Writerside/topics/memory.md	Sat Feb 15 17:43:21 2025 +0100
@@ -10,4 +10,4 @@
 
 > Although not part of the public API, UCX is also implementing the allocator interface
 > in its own test suite: `CxTestingAllocator`. This allocator keeps track of memory allocations
-> and de-allocations with the goal to detect memory management errors.  
+> and deallocations with the goal to detect memory management errors.  
--- a/docs/Writerside/topics/printf.h.md	Sat Feb 15 16:36:29 2025 +0100
+++ b/docs/Writerside/topics/printf.h.md	Sat Feb 15 17:43:21 2025 +0100
@@ -6,26 +6,36 @@
 With the help of these convenience functions, you do not need the libc `snprintf` to print your string to a temporary buffer anymore,
 plus you do not need to worry about too small buffer sizes, because the functions will automatically allocate enough memory to contain the entire formatted string.
 
+> Although UCX usually uses `size_t` for sizes, the return type of all `printf`-like functions
+> (except for the `cx_asprintf()` family of functions) is `int`, consistent with the stdio `printf` return type.
+{style="note"}
+
 ## Print to Streams and Buffers
 
 ```C
 #include <cx/printf.h>
 
 int cx_fprintf(void *stream, cx_write_func wfc,
-               const char *fmt, ...);
+        const char *fmt, ...);
 
 int cx_vfprintf(void *stream, cx_write_func wfc,
-                const char *fmt, va_list ap);
+        const char *fmt, va_list ap);
 
 int cx_bprintf(CxBuffer *buf, const char *fmt, ...);
 ```
 
-> TODO: document
-{style="warning"}
+The `cx_fprintf()` function uses the stdio `snprintf()` to prepare a formatted string
+which is then written to the `stream` using the write function `wfc`.
+The return value is the number of bytes written or a value less than zero when an error occurred.
+If the resulting string is short enough, no additional memory is allocated on the heap.
+See the Section about [](#small-buffer-optimization) for more details.
 
 The `cx_vfprintf()` function is equivalent to `cx_fprintf()`,
 except that instead of being called with a variable number of arguments,
-they are called with an argument list as defined by `<stdarg.h>`.
+it is called with an argument list as defined by `<stdarg.h>`.
+
+The `cx_bprintf()` function is implemented as macro for `cx_fprintf()` with the
+`CxBuffer` as `stream` and the `cxBufferWriteFunc` as write function.
 
 ## Print to Freshly Allocated Memory
 
@@ -35,16 +45,18 @@
 cxmutstr cx_asprintf(const char *fmt, ...);
 
 cxmutstr cx_asprintf_a(const CxAllocator *allocator,
-                       const char *fmt, ...);
+        const char *fmt, ...);
 
 cxmutstr cx_vasprintf(const char *fmt, va_list ap);
 
 cxmutstr cx_vasprintf_a(const CxAllocator *allocator,
-                        const char *fmt, va_list ap);
+        const char *fmt, va_list ap);
 ```
 
-> TODO: document
-{style="warning"}
+The `cx_asprintf()` and `cx_asprintf_a()` functions print the formatted output directly to a freshly allocated
+string which is then returned from the function.
+On platforms (or when using allocators) where allocation can fail,
+the returned string may be empty and the `ptr` field set to `NULL`. 
 
 The `cx_vasprintf()` and `cx_vasprintf_a()` functions are equivalent to `cx_asprintf()` and `cx_asprintf_a()`,
 except that instead of being called with a variable number of arguments,
@@ -55,18 +67,51 @@
 ```C
 #include <cx/printf.h>
 
-cx_sprintf
-cx_sprintf_a
-cx_sprintf_s
-cx_sprintf_sa
-cx_vsprintf
-cx_vsprintf_a
-cx_vsprintf_s
-cx_vsprintf_sa
+int cx_sprintf(char **str, size_t *len,
+        const char *fmt, ...);
+
+int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len,
+        const char *fmt, ...);
+
+int cx_sprintf_s(char *buf, size_t *len, char **str,
+        const char *fmt, ...);
+
+int cx_sprintf_sa(CxAllocator *alloc,
+        char *buf, size_t *len, char **str,
+        const char *fmt, ...);
+
+int cx_vsprintf(char **str, size_t *len,
+        const char *fmt, va_list ap);
+
+int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len,
+        const char *fmt, va_list ap);
+
+int cx_vsprintf_s(char *buf, size_t *len, char **str,
+        const char *fmt, ...);
+
+int cx_vsprintf_sa(CxAllocator *alloc,
+        char *buf, size_t *len, char **str,
+        const char *fmt, va_list ap);
 ```
 
-> TODO: document
-{style="warning"}
+The `cx_sprintf()` and `cx_sprintf_a()` functions take a pointer `str` to a pointer to a pre-allocated buffer,
+as well as a pointer `len` to `*str`'s length.
+If the formatted output would not fit into this buffer, it is reallocated
+and the new pointer to the buffer and the new length are written back to the variables pointed to by `str` and `len`.
+
+The `cx_sprintf_s()` and `cx_sprintf_sa()` functions differ from the previous function in that they take
+the pointer to the pre-allocated buffer in the `buf` argument and not in the `str` argument
+(which in this case is only used for storing the resulting pointer), and _always_ allocate an entirely new buffer
+when the length is insufficient.
+This is particularly useful when you want to print the formatted string to a buffer allocated on the stack, but also
+want the option to switch to heap-allocated memory when necessary.
+
+In other words: when the formatted output fits into the buffer pointed to by `buf`, `buf` will be written to `*str`.
+Otherwise, the pointer to the freshly allocated buffer is written to `*str`.
+
+> When using `cx_sprintf()` or `cx_sprintf_a()` you should always make sure that the string pointed to by `*str`
+> was allocated by a matching allocator.
+> This restriction does not apply for `cx_sprintf_s()` or `cx_sprintf_sa()` which would allocate a fresh buffer when needed.
 
 The `cx_vsprintf()`, `cx_vsprintf_a()`, `cx_vsprintf_s()`, and `cx_vsprintf_sa()` functions are equivalent
 to `cx_sprintf()`, `cx_sprintf_a()`, `cx_sprintf_s()`, and `cx_sprintf_sa()`,
--- a/docs/Writerside/topics/streams.h.md	Sat Feb 15 16:36:29 2025 +0100
+++ b/docs/Writerside/topics/streams.h.md	Sat Feb 15 17:43:21 2025 +0100
@@ -9,27 +9,19 @@
 ```C
 #include <cx/streams.h>
 
-size_t cx_stream_copy(
-    void *src, void *dest,
-    cx_read_func rfnc, cx_write_func wfnc
-);
-size_t cx_stream_ncopy(
-    void *src, void *dest,
-    cx_read_func rfnc, cx_write_func wfnc,
-    size_t n
-);
+size_t cx_stream_copy(void *src, void *dest,
+        cx_read_func rfnc, cx_write_func wfnc);
+        
+size_t cx_stream_ncopy(void *src, void *dest,
+        cx_read_func rfnc, cx_write_func wfnc, size_t n);
 
-size_t cx_stream_bcopy(
-    void *src, void *dest,
-    cx_read_func rfnc, cx_write_func wfnc,
-    char *buf, size_t bufsize
-);
-size_t cx_stream_bncopy(
-    void *src, void *dest,
-    cx_read_func rfnc, cx_write_func wfnc,
-    char *buf, size_t bufsize,
-    size_t n
-);
+size_t cx_stream_bcopy(void *src, void *dest,
+        cx_read_func rfnc, cx_write_func wfnc,
+        char *buf, size_t bufsize);
+
+size_t cx_stream_bncopy(void *src, void *dest,
+        cx_read_func rfnc, cx_write_func wfnc,
+        char *buf, size_t bufsize, size_t n);
 ``` 
 
 ## Description

mercurial