commit 93ad86974a4ffa9907a66a7ca441bfb54d95250e
parent 99fe39ccd3388bf966db0f8b6c03f349c641b5b6
Author: vaplv <vaplv@free.fr>
Date: Thu, 17 Sep 2020 10:53:52 +0200
Merge branch 'release_0.10'
Diffstat:
11 files changed, 668 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
@@ -17,6 +17,26 @@ project can be now edited, built, tested and installed as any CMake project.
## Release notes
+### Version 0.10
+
+- Add the `str_vprintf` and `str_append_[v]printf` functions to the string API
+ that sets the string content or appends text to it, respectively. The input
+ text is formatted following the `[v]printf` syntax, i.e. a literal is used to
+ format the text and a variable list of data are either provided directly as
+ function arguments (`printf`) or through a `va_list` (`vprintf`).
+- Add macros and functions to deal with data endianness. The `BYTE_ORDER` macro
+ defines the endianness of the host; its value can be `LITTLE_ENDIAN` or
+ `BIG_ENDIAN`. The `byte_swap_<16|32|64>` functions revert the byte ordering
+ of the submitted unsigned integer of 16, 32 or 64 bits. Finally, the
+ `<little|big>_endian_<16|32|64>` functions ensure that the input unsigned
+ integer follows the little or big endian ordering: bytes are swapped only if
+ the host endianness is not the expected one.
+- Add support of 256 bits hash. The `hash_sha256` function digest input data
+ wrt to the SHA-256 cryptographic hash algorithm. The `hash256_to_cstr`
+ function converts a 256 bits hash to its corresponding lower case string.
+ Finally The `hash256_eq` function check that the submitted 256 bits hashes
+ are the same.
+
### Version 0.9.1
- Add the `VFATAL` macro that works as the regular `FATAL` macro but with an
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -38,13 +38,14 @@ include(rcmake)
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 9)
-set(VERSION_PATCH 1)
+set(VERSION_MINOR 10)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(RSYS_FILES_SRC
clock_time.c
cstr.c
+ hash.c
image.c
library.c
logger.c
@@ -90,6 +91,7 @@ set(RSYS_FILES_INC_API
dynamic_array_uint.h
dynamic_array_size_t.h
dynamic_array_str.h
+ endianness.h
float2.h
float3.h
float4.h
@@ -209,6 +211,7 @@ if(NOT NO_TEST)
new_test(test_double22)
new_test(test_double33 ${MATH_LIB})
new_test(test_double44)
+ new_test(test_endianness)
new_test(test_dynamic_array rsys)
new_test(test_float2 ${MATH_LIB})
new_test(test_float3 ${MATH_LIB})
@@ -219,6 +222,7 @@ if(NOT NO_TEST)
new_test(test_free_list rsys)
new_test(test_func_name)
new_test(test_hash_table rsys)
+ new_test(test_hash_sha256 rsys)
new_test(test_image rsys)
new_test(test_library rsys)
new_test(test_list rsys)
diff --git a/src/endianness.h b/src/endianness.h
@@ -0,0 +1,124 @@
+/* Copyright (C) 2013-2020 Vincent Forest (vaplv@free.fr)
+ *
+ * The RSys library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The RSys library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef ENDIANNESS_H
+#define ENDIANNESS_H
+
+#include "rsys.h"
+
+#if defined(COMPILER_GCC)
+ #define BYTE_ORDER __BYTE_ORDER__
+ #define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
+ #define BIG_ENDIAN __ORDER_BIG_ENDIAN__
+ #include <byteswap.h>
+#elif defined(COMPILER_CL)
+ #include <Windows.h>
+ #define BYTE_ORDER REG_DWORD
+ #define LITTLE_ENDIAN REG_DWORD_LITTLE_ENDIAN
+ #define BIG_ENDIAN REG_DWORD_BIG_ENDIAN
+#else
+ #error "Undefined byte ordering macros"
+#endif
+
+#ifdef COMPILER_GCC
+static FINLINE uint16_t byte_swap_16(const uint16_t ui) { return bswap_16(ui); }
+static FINLINE uint32_t byte_swap_32(const uint32_t ui) { return bswap_32(ui); }
+static FINLINE uint64_t byte_swap_64(const uint64_t ui) { return bswap_64(ui); }
+
+#elif defined COMPILER_CL
+static FINLINE uint16_t
+byte_swap_16(const uint16_t ui)
+{
+ STATIC_ASSERT(sizeof(unsigned short) == sizeof(uint16_t),
+ Unexpected_sizeof_ushort);
+ return _byteswap_ushort(ui);
+}
+
+static FINLINE uint32_t
+byte_swap_32(const uint32_t ui)
+{
+ STATIC_ASSERT(sizeof(unsigned long) == sizeof(uint32_t),
+ Unexpected_sizeof_ushort);
+ return _byteswap_ulong(ui);
+}
+
+static FINLINE uint64_t
+byte_swap_64(const uint64_t ui)
+{
+ return _byteswap_uint64(ui);
+}
+#endif
+
+static FINLINE uint16_t
+little_endian_16(const uint16_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return ui;
+#elif BYTE_ORDER == BIG_ENDIAN
+ return byte_swap_16(ui);
+#endif
+}
+
+static FINLINE uint32_t
+little_endian_32(const uint32_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return ui;
+#elif BYTE_ORDER == BIG_ENDIAN
+ return byte_swap_32(ui);
+#endif
+}
+
+static FINLINE uint64_t
+little_endian_64(const uint64_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return ui;
+#elif BYTE_ORDER == BIG_ENDIAN
+ return byte_swap_64(ui);
+#endif
+}
+
+static FINLINE uint16_t
+big_endian_16(const uint16_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return byte_swap_16(ui);
+#elif BYTE_ORDER == BIG_ENDIAN
+ return ui;
+#endif
+}
+
+static FINLINE uint32_t
+big_endian_32(const uint32_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return byte_swap_32(ui);
+#elif BYTE_ORDER == BIG_ENDIAN
+ return ui;
+#endif
+}
+
+static FINLINE uint64_t
+big_endian_64(const uint64_t ui)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return byte_swap_64(ui);
+#elif BYTE_ORDER == BIG_ENDIAN
+ return ui;
+#endif
+}
+
+#endif /* ENDIANNESS_H */
diff --git a/src/hash.c b/src/hash.c
@@ -0,0 +1,192 @@
+/* Copyright (C) 2013-2020 Vincent Forest (vaplv@free.fr)
+ *
+ * The RSys library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The RSys library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200112L
+
+#include "endianness.h"
+#include "hash.h"
+#include "mem_allocator.h"
+
+#include <string.h>
+
+/* Array of round constants: first 32 bits of the fractional parts of the cube
+ * roots of the first 64 primes 2..311 */
+static const uint32_t k[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+/* Right rotation */
+static FINLINE uint32_t
+rrot(const uint32_t ui, const unsigned int count)
+{
+ ASSERT(count <= 32);
+ return ui >> count | ui << (32 - count);
+}
+
+static size_t
+create_msg
+ (struct mem_allocator* allocator,
+ const void* data,
+ const size_t len,
+ char** out_msg)
+{
+ char* msg = NULL;
+ size_t msg_sz = 0;
+ ASSERT(allocator && out_msg);
+
+ msg_sz = ALIGN_SIZE(len + 1/*Byte of the '1' bit*/ + 8/*message len*/, 64u);
+ msg = MEM_ALLOC(allocator, msg_sz);
+ if(!msg) goto error;
+
+ memcpy(msg, data, len);
+
+ /* Setup the '1' bit that marks the end of the msg */
+ msg[len] = (char)0x80u;
+ /* Clean up the bytes after the msg up to the last 8 bytes */
+ memset(msg+len+1, 0, msg_sz - len - 1 - 8);
+ /* Store the message 8*len in big endian */
+ *(uint64_t*)(msg+msg_sz-8) = big_endian_64(len*8);
+
+exit:
+ *out_msg = msg;
+ return msg_sz;
+
+error:
+ msg_sz = 0;
+ if(msg) { MEM_RM(allocator, msg); msg = NULL; }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+hash_sha256
+ (struct mem_allocator* mem_allocator,
+ const void* data,
+ const size_t len,
+ hash256_T hash)
+{
+ struct mem_allocator* allocator = NULL;
+ char* msg = NULL;
+ size_t msg_sz = 0;
+ size_t ichunk = 0;
+ size_t nchunks = 0;
+ res_T res = RES_OK;
+
+ /* Initial hash values: first 32 bits of the fractional parts of the square
+ * roots of the first 8 primes 2..19 */
+ uint32_t h0 = 0x6a09e667;
+ uint32_t h1 = 0xbb67ae85;
+ uint32_t h2 = 0x3c6ef372;
+ uint32_t h3 = 0xa54ff53a;
+ uint32_t h4 = 0x510e527f;
+ uint32_t h5 = 0x9b05688c;
+ uint32_t h6 = 0x1f83d9ab;
+ uint32_t h7 = 0x5be0cd19;
+ ASSERT(hash);
+
+ allocator = mem_allocator ? mem_allocator : &mem_default_allocator;
+
+ msg_sz = create_msg(allocator, data, len, &msg);
+ if(!msg) { res = RES_MEM_ERR; goto error; }
+
+ ASSERT((msg_sz % 64) == 0);
+ nchunks = msg_sz / 64; /* #chunks of 512 bits */
+
+ FOR_EACH(ichunk, 0, nchunks) {
+ const char* chunk = msg + ichunk*64;
+ uint32_t w[64] = {0};
+ uint32_t a=h0, b=h1, c=h2, d=h3, e=h4, f=h5, g=h6, h=h7;
+ int i;
+
+ FOR_EACH(i, 0, 16) {
+ w[i] = big_endian_32(((uint32_t*)chunk)[i]);
+ }
+ FOR_EACH(i, 16, 64) {
+ const uint32_t s0 = rrot(w[i-15],7) ^ rrot(w[i-15],18) ^ (w[i-15] >> 3);
+ const uint32_t s1 = rrot(w[i-2],17) ^ rrot(w[i-2], 19) ^ (w[i-2] >> 10);
+ w[i] = w[i-16] + s0 + w[i-7] + s1;
+ }
+
+ /* Compress the chunk */
+ FOR_EACH(i, 0, 64) {
+ const uint32_t s1 = rrot(e, 6) ^ rrot(e, 11) ^ rrot(e, 25);
+ const uint32_t ch = (e & f) ^ ((~e) & g);
+ const uint32_t tmp1 = h + s1 + ch + k[i] + w[i];
+ const uint32_t s0 = rrot(a, 2) ^ rrot(a, 13) ^ rrot(a, 22);
+ const uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
+ const uint32_t tmp2 = s0 + maj;
+
+ h = g;
+ g = f;
+ f = e;
+ e = d + tmp1;
+ d = c;
+ c = b;
+ b = a;
+ a = tmp1 + tmp2;
+ }
+
+ /* Update hash with the current compressed chunk */
+ h0+=a; h1+=b; h2+=c; h3+=d; h4+=e; h5+=f; h6+=g; h7+=h;
+ }
+
+ /* Write the results */
+ ((uint32_t*)hash)[0] = big_endian_32(h0);
+ ((uint32_t*)hash)[1] = big_endian_32(h1);
+ ((uint32_t*)hash)[2] = big_endian_32(h2);
+ ((uint32_t*)hash)[3] = big_endian_32(h3);
+ ((uint32_t*)hash)[4] = big_endian_32(h4);
+ ((uint32_t*)hash)[5] = big_endian_32(h5);
+ ((uint32_t*)hash)[6] = big_endian_32(h6);
+ ((uint32_t*)hash)[7] = big_endian_32(h7);
+
+exit:
+ if(msg) MEM_RM(allocator, msg);
+ return res;
+error:
+ goto exit;
+}
+
+void
+hash256_to_cstr(const hash256_T hash, char cstr[65])
+{
+ size_t i;
+ ASSERT(hash && cstr);
+ FOR_EACH(i, 0, sizeof(hash256_T)) {
+ sprintf(cstr+i*2, "%02x", (uint8_t)hash[i]);
+ }
+}
+
+int
+hash256_eq(const hash256_T hash0, const hash256_T hash1)
+{
+ return memcmp(hash0, hash1, sizeof(hash256_T)) == 0;
+}
+
diff --git a/src/hash.h b/src/hash.h
@@ -18,6 +18,10 @@
#include "rsys.h"
+struct mem_allocator;
+
+typedef char hash256_T[32];
+
/* 32-bits Fowler/Noll/Vo hash function */
static INLINE uint32_t
hash_fnv32(const void* data, const size_t len)
@@ -56,5 +60,26 @@ hash_fnv64(const void* data, const size_t len)
return hash;
}
+BEGIN_DECLS
+
+RSYS_API res_T
+hash_sha256
+ (struct mem_allocator* allocator,
+ const void* data,
+ const size_t len,
+ hash256_T hash);
+
+RSYS_API void
+hash256_to_cstr
+ (const hash256_T hash,
+ char cstr[65]);
+
+RSYS_API int
+hash256_eq
+ (const hash256_T hash0,
+ const hash256_T hash1);
+
+END_DECLS
+
#endif /* HASH_H */
diff --git a/src/str.c b/src/str.c
@@ -17,7 +17,6 @@
#include "io_c99.h"
#include "str.h"
-#include <stdarg.h>
#include <string.h>
/*******************************************************************************
@@ -185,22 +184,57 @@ res_T
str_printf(struct str* str, const char* fmt, ...)
{
va_list ap;
- size_t len;
res_T res = RES_OK;
ASSERT(str && fmt);
+ va_start(ap, fmt);
+ res = str_vprintf(str, fmt, ap);
+ va_end(ap);
+ return res;
+}
+res_T
+str_append_printf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ res_T res = RES_OK;
+ ASSERT(str && fmt);
va_start(ap, fmt);
- len = (size_t)vsnprintf(str->cstr, str->allocated, fmt, ap);
+ res = str_append_vprintf(str, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
+res_T
+str_vprintf(struct str* str, const char* fmt, va_list vargs_list)
+{
+ ASSERT(str && fmt);
+ str_clear(str);
+ return str_append_vprintf(str, fmt, vargs_list);
+}
+
+res_T
+str_append_vprintf(struct str* str, const char* fmt, va_list vargs_list)
+{
+ va_list ap;
+ size_t flen; /* Length of the formatted message */
+ size_t slen; /* Length of the string */
+ res_T res = RES_OK;
+ ASSERT(str && fmt);
+
+ slen = str_len(str);
+
+ VA_COPY(ap, vargs_list);
+ flen = (size_t)vsnprintf(str->cstr + slen, str->allocated - slen, fmt, ap);
va_end(ap);
- if(len >= str->allocated) {
- res = ensure_allocated(str, len + 1/* Null char */, 0);
+ if(slen + flen >= str->allocated) {
+ res = ensure_allocated(str, slen + flen + 1/* Null char */, 1);
if(res != RES_OK) goto error;
- va_start(ap, fmt);
- len = (size_t)vsnprintf(str->cstr, str->allocated, fmt, ap);
+ VA_COPY(ap, vargs_list);
+ flen = (size_t)vsnprintf(str->cstr + slen, str->allocated - slen, fmt, ap);
va_end(ap);
- CHK(len < str->allocated);
+ CHK(slen + flen < str->allocated);
}
exit:
diff --git a/src/str.h b/src/str.h
@@ -19,6 +19,8 @@
#include "hash.h"
#include "mem_allocator.h"
#include "rsys.h"
+
+#include <stdarg.h>
#include <string.h>
struct str {
@@ -115,6 +117,28 @@ str_printf
#endif
;
+RSYS_API res_T
+str_append_printf
+ (struct str* str,
+ const char* fmt,
+ ...)
+#ifdef COMPILER_GCC
+ __attribute__((format(printf, 2, 3)))
+#endif
+;
+
+RSYS_API res_T
+str_vprintf
+ (struct str* str,
+ const char* fmt,
+ va_list vargs_list);
+
+RSYS_API res_T
+str_append_vprintf
+ (struct str* str,
+ const char* fmt,
+ va_list vargs_list);
+
END_DECLS
static INLINE res_T
diff --git a/src/test_endianness.c b/src/test_endianness.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2013-2020 Vincent Forest (vaplv@free.fr)
+ *
+ * The RSys library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The RSys library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "endianness.h"
+
+int
+main(int argc, char** argv)
+{
+ uint16_t ui16 = 0x0123;
+ uint32_t ui32 = 0x01234567;
+ uint64_t ui64 = 0x0123456789ABCDEF;
+ (void)argc, (void)argv;
+
+ CHK(byte_swap_16(ui16) == 0x2301);
+ CHK(byte_swap_32(ui32) == 0x67452301);
+ CHK(byte_swap_64(ui64) == 0xEFCDAB8967452301);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ CHK(little_endian_16(ui16) == ui16);
+ CHK(little_endian_32(ui32) == ui32);
+ CHK(little_endian_64(ui64) == ui64);
+ CHK(big_endian_16(ui16) == byte_swap_16(ui16));
+ CHK(big_endian_32(ui32) == byte_swap_32(ui32));
+ CHK(big_endian_64(ui64) == byte_swap_64(ui64));
+
+#elif BYTE_ORDER == BIG_ENDIAN
+ CHK(little_endian_16(ui16) == byte_swap_16(ui16));
+ CHK(little_endian_32(ui32) == byte_swap_32(ui32));
+ CHK(little_endian_64(ui64) == byte_swap_64(ui64));
+ CHK(big_endian_16(ui16) == ui16);
+ CHK(big_endian_32(ui32) == ui32);
+ CHK(big_endian_64(ui64) == ui64);
+
+#else
+ #error "Undefined endianness"
+#endif
+
+ return 0;
+}
diff --git a/src/test_hash_sha256.c b/src/test_hash_sha256.c
@@ -0,0 +1,133 @@
+/* Copyright (C) 2013-2020 Vincent Forest (vaplv@free.fr)
+ *
+ * The RSys library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The RSys library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "endianness.h"
+#include "hash.h"
+#include "mem_allocator.h"
+#include <string.h>
+
+struct test_str {
+ const char* str;
+ const char* sha256sum;
+};
+struct test_data {
+ const void* mem;
+ const size_t len;
+ const char* sha256sum;
+};
+
+static void
+chk_hash(const void* data, const size_t data_len, const char* sha256sum)
+{
+ hash256_T hash;
+ char hash_str[65];
+ ASSERT(sha256sum);
+ CHK(hash_sha256(NULL, data, data_len, hash) == RES_OK);
+ hash256_to_cstr(hash, hash_str);
+ CHK(!strcmp(hash_str, sha256sum));
+}
+
+int
+main(int argc, char** argv)
+{
+ char* data = NULL;
+ hash256_T hash0, hash1;
+ (void)argc, (void)argv;
+
+ data = mem_alloc(0x6000003e);
+ CHK(data);
+
+ data[0] = '\0';
+ chk_hash(data, 0,
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+
+ CHK(hash_sha256(&mem_default_allocator, data, 0, hash0) == RES_OK);
+ ((uint32_t*)hash1)[0] = big_endian_32(0xe3b0c442);
+ ((uint32_t*)hash1)[1] = big_endian_32(0x98fc1c14);
+ ((uint32_t*)hash1)[2] = big_endian_32(0x9afbf4c8);
+ ((uint32_t*)hash1)[3] = big_endian_32(0x996fb924);
+ ((uint32_t*)hash1)[4] = big_endian_32(0x27ae41e4);
+ ((uint32_t*)hash1)[5] = big_endian_32(0x649b934c);
+ ((uint32_t*)hash1)[6] = big_endian_32(0xa495991b);
+ ((uint32_t*)hash1)[7] = big_endian_32(0x7852b855);
+ CHK(hash256_eq(hash0, hash1));
+
+ sprintf(data, "abc");
+ chk_hash(data, strlen(data),
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+
+ sprintf(data, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ chk_hash(data, strlen(data),
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
+
+ data[0] = (char)0xbdu;
+ chk_hash(data, 1,
+ "68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b");
+
+ data[0] = (char)0xc9u;
+ data[1] = (char)0x8cu;
+ data[2] = (char)0x8eu;
+ data[3] = (char)0x55u;
+ chk_hash(data, 4,
+ "7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504");
+
+ memset(data, 0, 55);
+ chk_hash(data, 55,
+ "02779466cdec163811d078815c633f21901413081449002f24aa3e80f0b88ef7");
+
+ memset(data, 0, 56);
+ chk_hash(data, 56,
+ "d4817aa5497628e7c77e6b606107042bbba3130888c5f47a375e6179be789fbb");
+
+ memset(data, 0, 57);
+ chk_hash(data, 57,
+ "65a16cb7861335d5ace3c60718b5052e44660726da4cd13bb745381b235a1785");
+
+ memset(data, 0, 64);
+ chk_hash(data, 64,
+ "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b");
+
+ memset(data, 0, 1000);
+ chk_hash(data, 1000,
+ "541b3e9daa09b20bf85fa273e5cbd3e80185aa4ec298e765db87742b70138a53");
+
+ memset(data, 'A', 1000);
+ chk_hash(data, 1000,
+ "c2e686823489ced2017f6059b8b239318b6364f6dcd835d0a519105a1eadd6e4");
+
+ memset(data, 'U', 1005);
+ chk_hash(data, 1005,
+ "f4d62ddec0f3dd90ea1380fa16a5ff8dc4c54b21740650f24afc4120903552b0");
+
+ memset(data, 0, 1000000);
+ chk_hash(data, 1000000,
+ "d29751f2649b32ff572b5e0a9f541ea660a50f94ff0beedfb0b692b924cc8025");
+
+ memset(data, 'Z', 0x20000000);
+ chk_hash(data, 0x20000000,
+ "15a1868c12cc53951e182344277447cd0979536badcc512ad24c67e9b2d4f3dd");
+
+ memset(data, 0, 0x41000000);
+ chk_hash(data, 0x41000000,
+ "461c19a93bd4344f9215f5ec64357090342bc66b15a148317d276e31cbc20b53");
+
+ memset(data, 'B', 0x6000003e);
+ chk_hash(data, 0x6000003e,
+ "c23ce8a7895f4b21ec0daf37920ac0a262a220045a03eb2dfed48ef9b05aabea");
+
+ mem_rm(data);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
diff --git a/src/test_str.c b/src/test_str.c
@@ -15,8 +15,34 @@
#include "str.h"
#include "test_utils.h"
+#include <stdarg.h>
#include <string.h>
+#ifdef COMPILER_GCC
+__attribute__((format(printf, 2, 3)))
+#endif
+static void
+chk_vprintf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ CHK(str_vprintf(str, fmt, ap) == RES_OK);
+ va_end(ap);
+}
+
+#ifdef COMPILER_GCC
+__attribute__((format(printf, 2, 3)))
+#endif
+static void
+chk_append_vprintf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ CHK(str_append_vprintf(str, fmt, ap) == RES_OK);
+ va_end(ap);
+}
+
+
int
main(int argc, char** argv)
{
@@ -150,6 +176,25 @@ main(int argc, char** argv)
str_release(&str);
str_init(&allocator_proxy, &str);
+ CHK(str_printf(&str, "Hello, ") == RES_OK);
+ CHK(str_append_printf(&str, "world!") == RES_OK);
+ CHK(!strcmp(str_cget(&str), "Hello, world!"));
+ CHK(str_printf(&str, "%s:%lu", __FILE__, 0xDECAFBADlu) == RES_OK);
+ CHK(str_append_printf(&str, ":%s", __FILE__) == RES_OK);
+ CHK(!strcmp(str_cget(&str), __FILE__":3737844653:"__FILE__));
+ chk_vprintf(&str, "You should have received a copy of the %s %s %d",
+ "GNU", "Lesser General Public License", 3);
+ CHK(!strcmp(str_cget(&str),
+ "You should have received a copy of the "
+ "GNU Lesser General Public License 3"));
+ chk_append_vprintf(&str, " along with the %s library. If not, see %c%s%c.",
+ "RSys", '<', "http://www.gnu.org/licenses/", '>');
+ CHK(!strcmp(str_cget(&str),
+ "You should have received a copy of the GNU Lesser General Public License 3 "
+ "along with the RSys library. If not, see <http://www.gnu.org/licenses/>."));
+ str_release(&str);
+
+ str_init(&allocator_proxy, &str);
CHK(str_set(&str, "abcd") == RES_OK);
CHK(str_len(&str) == 4);
str_get(&str)[3] = '\0';
diff --git a/src/test_text_reader.c b/src/test_text_reader.c
@@ -77,7 +77,8 @@ main(int argc, char** argv)
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
/* Write the text into a stream */
- CHK(stream = fopen(filename, "w+"));
+ stream = fopen(filename, "w+");
+ CHK(stream);
FOR_EACH(i, 0, nlines) {
const size_t len = strlen(text[i]);
CHK(fwrite(text[i], 1, len, stream) == len);
@@ -102,7 +103,8 @@ main(int argc, char** argv)
check_text_reader(txtrdr);
txtrdr_ref_put(txtrdr);
- CHK(stream = freopen(filename, "w+", stream));
+ stream = freopen(filename, "w+", stream);
+ CHK(stream);
fprintf(stream, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
fprintf(stream, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
rewind(stream);
@@ -110,7 +112,8 @@ main(int argc, char** argv)
CHK(txtrdr_read_line(txtrdr) == RES_OK);
txtrdr_ref_put(txtrdr);
- CHK(stream = freopen(filename, "w+", stream));
+ stream = freopen(filename, "w+", stream);
+ CHK(stream);
fprintf(stream, "\r\n");
rewind(stream);
CHK(txtrdr_stream(&allocator, stream, filename, '#', &txtrdr) == RES_OK);