Tue, 13 Aug 2013 14:20:12 +0200
completed documentation + changed API for buffer/stream generic copy functions
test/buffer_tests.c | file | annotate | diff | comparison | revisions | |
test/buffer_tests.h | file | annotate | diff | comparison | revisions | |
test/main.c | file | annotate | diff | comparison | revisions | |
ucx/buffer.c | file | annotate | diff | comparison | revisions | |
ucx/buffer.h | file | annotate | diff | comparison | revisions | |
ucx/utils.c | file | annotate | diff | comparison | revisions | |
ucx/utils.h | file | annotate | diff | comparison | revisions |
1.1 --- a/test/buffer_tests.c Mon Aug 12 14:43:22 2013 +0200 1.2 +++ b/test/buffer_tests.c Tue Aug 13 14:20:12 2013 +0200 1.3 @@ -27,6 +27,7 @@ 1.4 */ 1.5 1.6 #include "buffer_tests.h" 1.7 +#include "ucx/utils.h" 1.8 1.9 UCX_TEST(test_ucx_buffer_seektell) { 1.10 UcxBuffer *b = ucx_buffer_new(NULL, 32, UCX_BUFFER_DEFAULT); 1.11 @@ -292,7 +293,7 @@ 1.12 ucx_buffer_free(src); 1.13 } 1.14 1.15 -UCX_TEST(test_ucx_buffer_generic_copy) { 1.16 +UCX_TEST(test_ucx_stream_copy) { 1.17 UcxBuffer *b1 = ucx_buffer_new(NULL, 64, UCX_BUFFER_DEFAULT); 1.18 UcxBuffer *b2 = ucx_buffer_new(NULL, 2, UCX_BUFFER_AUTOEXTEND); 1.19 1.20 @@ -303,7 +304,7 @@ 1.21 UCX_TEST_ASSERT(b1->size == 16, "failed to fill buffer b1"); 1.22 ucx_buffer_seek(b1, 0, SEEK_SET); 1.23 1.24 - size_t ncp = ucx_buffer_copy(b1, b2, ucx_buffer_read, ucx_buffer_write); 1.25 + size_t ncp = ucx_stream_hcopy(b1, b2, ucx_buffer_read, ucx_buffer_write); 1.26 UCX_TEST_ASSERT(ncp == 16, "wrong number of copied bytes"); 1.27 UCX_TEST_ASSERT(b2->size == 16, "b2 has wrong size"); 1.28 UCX_TEST_ASSERT(memcmp(b1->space, b2->space, 16) == 0, 1.29 @@ -317,19 +318,25 @@ 1.30 FILE *file = tmpfile(); 1.31 UCX_TEST_ASSERT(file, "test file cannot be opened, test aborted"); 1.32 1.33 - ncp = ucx_buffer_copy(b1, file, ucx_buffer_read, fwrite); 1.34 + ncp = ucx_stream_hcopy(b1, file, ucx_buffer_read, fwrite); 1.35 UCX_TEST_ASSERT(ncp == 16, "copied wrong number of bytes to file"); 1.36 1.37 fseek(file, 0, SEEK_SET); 1.38 1.39 - ncp = ucx_buffer_copy(file, b2, fread, ucx_buffer_write); 1.40 + ncp = ucx_stream_hcopy(file, b2, fread, ucx_buffer_write); 1.41 UCX_TEST_ASSERT(ncp == 16, "copied wrong number of bytes from file"); 1.42 1.43 UCX_TEST_ASSERT(memcmp(b1->space, b2->space, 16) == 0, 1.44 "b1 and b2 content mismatch"); 1.45 1.46 fclose(file); 1.47 - 1.48 + 1.49 + ucx_buffer_clear(b1); 1.50 + ucx_buffer_seek(b2, 0, SEEK_SET); 1.51 + ncp = ucx_stream_ncopy(b2, b1, ucx_buffer_read, ucx_buffer_write, 8); 1.52 + UCX_TEST_ASSERT(ncp == 8, "copied wrong number of bytes with ncopy"); 1.53 + UCX_TEST_ASSERT(memcmp(b1->space, "01234567\0\0\0\0\0\0\0\0", 16) == 0, 1.54 + "content wrong after ncopy"); 1.55 1.56 UCX_TEST_END 1.57
2.1 --- a/test/buffer_tests.h Mon Aug 12 14:43:22 2013 +0200 2.2 +++ b/test/buffer_tests.h Tue Aug 13 14:20:12 2013 +0200 2.3 @@ -46,7 +46,7 @@ 2.4 UCX_TEST(test_ucx_buffer_write_ax); 2.5 UCX_TEST(test_ucx_buffer_read); 2.6 UCX_TEST(test_ucx_buffer_extract); 2.7 -UCX_TEST(test_ucx_buffer_generic_copy); 2.8 +UCX_TEST(test_ucx_stream_copy); 2.9 2.10 #ifdef __cplusplus 2.11 }
3.1 --- a/test/main.c Mon Aug 12 14:43:22 2013 +0200 3.2 +++ b/test/main.c Tue Aug 13 14:20:12 2013 +0200 3.3 @@ -176,7 +176,7 @@ 3.4 ucx_test_register(suite, test_ucx_buffer_write_ax); 3.5 ucx_test_register(suite, test_ucx_buffer_read); 3.6 ucx_test_register(suite, test_ucx_buffer_extract); 3.7 - ucx_test_register(suite, test_ucx_buffer_generic_copy); 3.8 + ucx_test_register(suite, test_ucx_stream_copy); 3.9 3.10 ucx_test_run(suite, stdout); 3.11 fflush(stdout);
4.1 --- a/ucx/buffer.c Mon Aug 12 14:43:22 2013 +0200 4.2 +++ b/ucx/buffer.c Tue Aug 13 14:20:12 2013 +0200 4.3 @@ -91,17 +91,16 @@ 4.4 } 4.5 4.6 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 4.7 - size_t npos = 0; 4.8 + size_t npos; 4.9 switch (whence) { 4.10 - case SEEK_SET: 4.11 - npos = 0; 4.12 - break; 4.13 case SEEK_CUR: 4.14 npos = buffer->pos; 4.15 break; 4.16 case SEEK_END: 4.17 npos = buffer->size; 4.18 break; 4.19 + default: 4.20 + npos = 0; 4.21 } 4.22 4.23 npos += offset; 4.24 @@ -210,51 +209,6 @@ 4.25 } 4.26 } 4.27 4.28 -size_t ucx_buffer_generic_copy(void *s1, void *s2, 4.29 - read_func readfnc, write_func writefnc, size_t bufsize) { 4.30 - size_t ncp = 0; 4.31 - char *buf = (char*)malloc(bufsize); 4.32 - if(buf == NULL) { 4.33 - return 0; 4.34 - } 4.35 - 4.36 - size_t r; 4.37 - while((r = readfnc(buf, 1, bufsize, s1)) != 0) { 4.38 - r = writefnc(buf, 1, r, s2); 4.39 - ncp += r; 4.40 - if(r == 0) { 4.41 - break; 4.42 - } 4.43 - } 4.44 - 4.45 - free(buf); 4.46 - return ncp; 4.47 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { 4.48 + return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 4.49 } 4.50 - 4.51 -size_t ucx_buffer_generic_ncopy(void *s1, void *s2, 4.52 - read_func readfnc, write_func writefnc, size_t bufsize, size_t n) { 4.53 - if(n == 0) { 4.54 - return 0; 4.55 - } 4.56 - 4.57 - size_t ncp = 0; 4.58 - char *buf = (char*)malloc(bufsize); 4.59 - if(buf == NULL) { 4.60 - return 0; 4.61 - } 4.62 - 4.63 - size_t r; 4.64 - size_t rn = bufsize > n ? n : bufsize; 4.65 - while((r = readfnc(buf, 1, rn, s1)) != 0) { 4.66 - r = writefnc(buf, 1, r, s2); 4.67 - ncp += r; 4.68 - n -= r; 4.69 - rn = bufsize > n ? n : bufsize; 4.70 - if(r == 0 || n == 0) { 4.71 - break; 4.72 - } 4.73 - } 4.74 - 4.75 - free(buf); 4.76 - return ncp; 4.77 -}
5.1 --- a/ucx/buffer.h Mon Aug 12 14:43:22 2013 +0200 5.2 +++ b/ucx/buffer.h Tue Aug 13 14:20:12 2013 +0200 5.3 @@ -26,6 +26,23 @@ 5.4 * POSSIBILITY OF SUCH DAMAGE. 5.5 */ 5.6 5.7 +/** 5.8 + * @file buffer.h 5.9 + * 5.10 + * Advanced buffer implementation. 5.11 + * 5.12 + * Instances of UcxBuffer can be used to read from or to write to like one 5.13 + * would do with a stream. This allows the use of ucx_stream_copy() to copy 5.14 + * contents from one buffer to another. 5.15 + * 5.16 + * Some features for convenient use of the buffer 5.17 + * can be enabled. See the documentation of the macro constants for more 5.18 + * information. 5.19 + * 5.20 + * @author Mike Becker 5.21 + * @author Olaf Wintermann 5.22 + */ 5.23 + 5.24 #ifndef UCX_BUFFER_H 5.25 #define UCX_BUFFER_H 5.26 5.27 @@ -37,94 +54,208 @@ 5.28 extern "C" { 5.29 #endif 5.30 5.31 -/* no autoextend or autofree behaviour */ 5.32 +/** 5.33 + * No buffer features enabled (all flags cleared). 5.34 + */ 5.35 #define UCX_BUFFER_DEFAULT 0x00 5.36 -/* the buffer shall free the occupied memory space */ 5.37 +/** 5.38 + * If this flag is enabled, the buffer will automatically free its contents. 5.39 + */ 5.40 #define UCX_BUFFER_AUTOFREE 0x01 5.41 -/* the buffer may automatically double its size on write operations */ 5.42 +/** 5.43 + * If this flag is enabled, the buffer will automatically extends its capacity. 5.44 + */ 5.45 #define UCX_BUFFER_AUTOEXTEND 0x02 5.46 5.47 -/* the user shall not modify values, but may get the latest pointer */ 5.48 +/** UCX Buffer. */ 5.49 typedef struct { 5.50 + /** A pointer to the buffer contents. */ 5.51 char *space; 5.52 + /** Current position of the buffer. */ 5.53 size_t pos; 5.54 + /** Current capacity (i.e. maximum size) of the buffer. */ 5.55 size_t capacity; 5.56 + /** Current size of the buffer content. */ 5.57 size_t size; 5.58 + /** 5.59 + * Flag register for buffer features. 5.60 + * @see #UCX_BUFFER_DEFAULT 5.61 + * @see #UCX_BUFFER_AUTOFREE 5.62 + * @see #UCX_BUFFER_AUTOEXTEND 5.63 + */ 5.64 int flags; 5.65 } UcxBuffer; 5.66 5.67 -/* if space is NULL, new space is allocated and the autofree flag is enforced */ 5.68 +/** 5.69 + * Creates a new buffer. 5.70 + * 5.71 + * <b>Note:</b> you may provide <code>NULL</code> as argument for 5.72 + * <code>space</code>. Then this function will allocate the space and enforce 5.73 + * the #UCX_BUFFER_AUTOFREE flag. 5.74 + * 5.75 + * @param space pointer to the memory area, or <code>NULL</code> to allocate 5.76 + * new memory 5.77 + * @param size the size of the buffer 5.78 + * @param flags buffer features (see UcxBuffer.flags) 5.79 + * @return the new buffer 5.80 + */ 5.81 UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags); 5.82 + 5.83 +/** 5.84 + * Destroys a buffer. 5.85 + * 5.86 + * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer 5.87 + * are also freed. 5.88 + * 5.89 + * @param buffer the buffer to destroy 5.90 + */ 5.91 void ucx_buffer_free(UcxBuffer* buffer); 5.92 5.93 -/* 5.94 - * the autofree flag is enforced for the new buffer 5.95 - * if length is zero, the whole remaining buffer shall be extracted 5.96 - * the position of the new buffer is set to zero 5.97 +/** 5.98 + * Creates a new buffer and fills it with extracted content from another buffer. 5.99 + * 5.100 + * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer. 5.101 + * 5.102 + * @param src the source buffer 5.103 + * @param start the start position of extraction 5.104 + * @param length the count of bytes to extract or 0 if all of the remaining 5.105 + * bytes shall be extracted 5.106 + * @param flags feature mask for the new buffer 5.107 + * @return 5.108 */ 5.109 UcxBuffer* ucx_buffer_extract(UcxBuffer *src, 5.110 size_t start, size_t length, int flags); 5.111 + 5.112 +/** 5.113 + * A shorthand macro for the full extraction of the buffer. 5.114 + * 5.115 + * @param src the source buffer 5.116 + * @param flags feature mask for the new buffer 5.117 + * @return a new buffer with the extracted content 5.118 + */ 5.119 #define ucx_buffer_clone(src,flags) \ 5.120 ucx_buffer_extract(src, 0, 0, flags) 5.121 5.122 -/* 5.123 - * Moves the position of the buffer to a new position relative to whence. 5.124 +/** 5.125 + * Moves the position of the buffer. 5.126 + * 5.127 + * The new position is relative to the <code>whence</code> argument. 5.128 * 5.129 - * SEEK_SET marks the start of the buffer 5.130 - * SEEK_CUR marks the current position 5.131 - * SEEK_END marks the first 0-byte in the buffer 5.132 - * 5.133 - * ucx_buffer_seek returns 0 on success and -1 if the new position is beyond the 5.134 - * bounds of the allocated buffer. In that case the position of the buffer 5.135 - * remains unchanged. 5.136 + * SEEK_SET marks the start of the buffer. 5.137 + * SEEK_CUR marks the current position. 5.138 + * SEEK_END marks the first 0-byte in the buffer. 5.139 + * 5.140 + * @param buffer 5.141 + * @param offset position offset relative to <code>whence</code> 5.142 + * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END 5.143 + * @return 0 on success, non-zero if the position is invalid 5.144 * 5.145 */ 5.146 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence); 5.147 5.148 -#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \ 5.149 - buffer->size = 0; buffer->pos = 0; 5.150 +/** 5.151 + * Clears the buffer by resetting the position and deleting the data. 5.152 + * 5.153 + * The data is deleted by a zeroing it with call to <code>memset()</code>. 5.154 + * 5.155 + * @param buffer the buffer to be cleared 5.156 + */ 5.157 +#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \ 5.158 + buffer->size = 0; buffer->pos = 0; 5.159 5.160 -/* 5.161 - * returns non-zero, if the current buffer position has exceeded the last 5.162 - * available byte of the underlying buffer 5.163 - * 5.164 +/** 5.165 + * Tests, if the buffer position has exceeded the buffer capacity. 5.166 + * 5.167 + * @param buffer the buffer to test 5.168 + * @return non-zero, if the current buffer position has exceeded the last 5.169 + * available byte of the buffer. 5.170 */ 5.171 int ucx_buffer_eof(UcxBuffer *buffer); 5.172 5.173 5.174 -int ucx_buffere_extend(UcxBuffer *buffer, size_t len); 5.175 +/** 5.176 + * Extends the capacity of the buffer. 5.177 + * 5.178 + * <b>Note:</b> The buffer capacity increased by a power of two. I.e. 5.179 + * the buffer capacity is doubled, as long as it would not hold the current 5.180 + * content plus the additional required bytes. 5.181 + * 5.182 + * <b>Attention:</b> the argument provided is the count of <i>additional</i> 5.183 + * bytes the buffer shall hold. It is <b>NOT</b> the total count of bytes the 5.184 + * buffer shall hold. 5.185 + * 5.186 + * @param buffer the buffer to extend 5.187 + * @param additional_bytes the count of additional bytes the buffer shall 5.188 + * <i>at least</i> hold 5.189 + * @return 0 on success or a non-zero value on failure 5.190 + */ 5.191 +int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes); 5.192 5.193 +/** 5.194 + * Writes data to an UcxBuffer. 5.195 + * 5.196 + * The position of the buffer is increased by the number of bytes read. 5.197 + * 5.198 + * @param ptr a pointer to the memory area containing the bytes to be written 5.199 + * @param size the length of one element 5.200 + * @param nitems the element count 5.201 + * @param buffer the UcxBuffer to write to 5.202 + * @return the total count of bytes written 5.203 + */ 5.204 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 5.205 UcxBuffer *buffer); 5.206 5.207 +/** 5.208 + * Reads data from an UcxBuffer. 5.209 + * 5.210 + * The position of the buffer is increased by the number of bytes read. 5.211 + * 5.212 + * @param ptr a pointer to the memory area where to store the read data 5.213 + * @param size the length of one element 5.214 + * @param nitems the element count 5.215 + * @param buffer the UcxBuffer to read from 5.216 + * @return the total count of bytes read 5.217 + */ 5.218 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 5.219 UcxBuffer *buffer); 5.220 5.221 -int ucx_buffer_putc(UcxBuffer *b, int c); 5.222 -int ucx_buffer_getc(UcxBuffer *b); 5.223 +/** 5.224 + * Writes a character to a buffer. 5.225 + * 5.226 + * The least significant byte of the argument is written to the buffer. If the 5.227 + * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled, 5.228 + * the buffer capacity is extended by ucx_buffer_extend(). If the feature is 5.229 + * disabled or buffer extension fails, <code>EOF</code> is returned. 5.230 + * 5.231 + * On successful write the position of the buffer is increased. 5.232 + * 5.233 + * @param buffer the buffer to write to 5.234 + * @param c the character to write as <code>int</code> value 5.235 + * @return the byte that has bean written as <code>int</code> value or 5.236 + * <code>EOF</code> when the end of the stream is reached and automatic 5.237 + * extension is not enabled or not possible 5.238 + */ 5.239 +int ucx_buffer_putc(UcxBuffer *buffer, int c); 5.240 5.241 +/** 5.242 + * Gets a character from a buffer. 5.243 + * 5.244 + * The current position of the buffer is increased after a successful read. 5.245 + * 5.246 + * @param buffer the buffer to read from 5.247 + * @return the character as <code>int</code> value or <code>EOF</code>, if the 5.248 + * end of the buffer is reached 5.249 + */ 5.250 +int ucx_buffer_getc(UcxBuffer *buffer); 5.251 5.252 -/* 5.253 - * copies all bytes from s1 to s2 5.254 - * uses the read function r to read from s1 und writes the data using the 5.255 - * write function w to s2 5.256 - * returns the number of bytes copied 5.257 +/** 5.258 + * Writes a string to a buffer. 5.259 + * 5.260 + * @param buffer the buffer 5.261 + * @param str the string 5.262 + * @return the number of bytes written 5.263 */ 5.264 -size_t ucx_buffer_generic_copy(void *s1, void *s2, read_func r, write_func w, 5.265 - size_t bufsize); 5.266 - 5.267 -size_t ucx_buffer_generic_ncopy(void *s1, void *s2, read_func r, write_func w, 5.268 - size_t bufsize, size_t n); 5.269 - 5.270 -#define UCX_DEFAULT_BUFFER_SIZE 0x1000 5.271 - 5.272 -#define ucx_buffer_copy(s1,s2,r,w) \ 5.273 - ucx_buffer_generic_copy(s1, s2, (read_func)r, (write_func)w, \ 5.274 - UCX_DEFAULT_BUFFER_SIZE) 5.275 - 5.276 -#define ucx_buffer_ncopy(s1,s2,r,w, n) \ 5.277 - ucx_buffer_generic_ncopy(s1, s2, (read_func)r, (write_func)w, \ 5.278 - UCX_DEFAULT_BUFFER_SIZE, n) 5.279 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str); 5.280 5.281 #ifdef __cplusplus 5.282 }
6.1 --- a/ucx/utils.c Mon Aug 12 14:43:22 2013 +0200 6.2 +++ b/ucx/utils.c Tue Aug 13 14:20:12 2013 +0200 6.3 @@ -27,7 +27,7 @@ 6.4 */ 6.5 6.6 #include "utils.h" 6.7 -#include "math.h" 6.8 +#include <math.h> 6.9 6.10 /* COPY FUCNTIONS */ 6.11 void* ucx_strcpy(void* s, void* data) { 6.12 @@ -45,6 +45,36 @@ 6.13 return cpy; 6.14 } 6.15 6.16 +size_t ucx_stream_copy(void *src, void *dest, read_func readfnc, 6.17 + write_func writefnc, char* buf, size_t bufsize, size_t n) { 6.18 + if(n == 0 || bufsize == 0) { 6.19 + return 0; 6.20 + } 6.21 + 6.22 + size_t ncp = 0; 6.23 + if (!buf) { 6.24 + buf = (char*)malloc(bufsize); 6.25 + if(buf == NULL) { 6.26 + return 0; 6.27 + } 6.28 + } 6.29 + 6.30 + size_t r; 6.31 + size_t rn = bufsize > n ? n : bufsize; 6.32 + while((r = readfnc(buf, 1, rn, src)) != 0) { 6.33 + r = writefnc(buf, 1, r, dest); 6.34 + ncp += r; 6.35 + n -= r; 6.36 + rn = bufsize > n ? n : bufsize; 6.37 + if(r == 0 || n == 0) { 6.38 + break; 6.39 + } 6.40 + } 6.41 + 6.42 + free(buf); 6.43 + return ncp; 6.44 +} 6.45 + 6.46 /* COMPARE FUNCTION */ 6.47 6.48 int ucx_strcmp(void *s1, void *s2, void *data) {
7.1 --- a/ucx/utils.h Mon Aug 12 14:43:22 2013 +0200 7.2 +++ b/ucx/utils.h Tue Aug 13 14:20:12 2013 +0200 7.3 @@ -43,6 +43,7 @@ 7.4 #endif 7.5 7.6 #include "ucx.h" 7.7 +#include <stdint.h> 7.8 #include <string.h> 7.9 7.10 /** 7.11 @@ -62,6 +63,50 @@ 7.12 */ 7.13 void *ucx_memcpy(void *m, void *n); 7.14 7.15 + 7.16 +/** 7.17 + * Reads data from a stream and writes it to another stream. 7.18 + * 7.19 + * @param src the source stream 7.20 + * @param dest the destination stream 7.21 + * @param rfnc the read function 7.22 + * @param wfnc the write function 7.23 + * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer 7.24 + * shall be implicitly created on the heap 7.25 + * @param bufsize the size of the copy buffer - if <code>NULL</code> was 7.26 + * provided for <code>buf</code>, this is the size of the buffer that shall be 7.27 + * implicitly created 7.28 + * @param n the maximum number of bytes that shall be copied 7.29 + * @return the total number of bytes copied 7.30 + */ 7.31 +size_t ucx_stream_copy(void *src, void *dest, read_func rfnc, write_func wfnc, 7.32 + char* buf, size_t bufsize, size_t n); 7.33 + 7.34 +/** 7.35 + * Shorthand for ucx_stream_copy using the default copy buffer. 7.36 + * 7.37 + * @param src the source stream 7.38 + * @param dest the destination stream 7.39 + * @param rfnc the read function 7.40 + * @param wfnc the write function 7.41 + * @return total number of bytes copied 7.42 + */ 7.43 +#define ucx_stream_hcopy(src,dest,rfnc,wfnc) ucx_stream_copy(\ 7.44 + src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, SIZE_MAX) 7.45 + 7.46 +/** 7.47 + * Shorthand for ucx_stream_copy using the default copy buffer and a copy limit. 7.48 + * 7.49 + * @param src the source stream 7.50 + * @param dest the destination stream 7.51 + * @param rfnc the read function 7.52 + * @param wfnc the write function 7.53 + * @param n maximum number of bytes that shall be copied 7.54 + * @return total number of bytes copied 7.55 + */ 7.56 +#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_copy(\ 7.57 + src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, n) 7.58 + 7.59 /** 7.60 * Wraps the strcmp function. 7.61 * @param s1 string one