diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | README | 40 | ||||
-rw-r--r-- | include/nsutils/assert.h | 24 | ||||
-rw-r--r-- | include/nsutils/base64.h | 73 | ||||
-rw-r--r-- | include/nsutils/endian.h | 71 | ||||
-rw-r--r-- | include/nsutils/time.h | 2 | ||||
-rw-r--r-- | include/nsutils/unistd.h | 2 | ||||
-rw-r--r-- | src/base64.c | 315 | ||||
-rw-r--r-- | src/time.c | 4 | ||||
-rw-r--r-- | src/unistd.c | 4 | ||||
-rw-r--r-- | test/base64.c | 84 | ||||
-rwxr-xr-x | test/runtest.sh | 64 |
12 files changed, 610 insertions, 79 deletions
@@ -2,11 +2,11 @@ # # Makefile for libnsutils # -# Copyright 2014-1015 Vincent Sanders <vince@netsurf-browser.org> +# Copyright 2014-2020 Vincent Sanders <vince@netsurf-browser.org> # Component settings COMPONENT := nsutils -COMPONENT_VERSION := 0.0.3 +COMPONENT_VERSION := 0.1.1 # Default to a static library COMPONENT_TYPE ?= lib-static @@ -49,8 +49,10 @@ include $(NSBUILD)/Makefile.top # Extra installation rules I := /$(INCLUDEDIR)/nsutils +INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/assert.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/errors.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/base64.h +INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/endian.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/time.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nsutils/unistd.h INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR)/pkgconfig:lib$(COMPONENT).pc.in @@ -0,0 +1,40 @@ +Libnsutils - NetSurf utility functions +====================================== + +Overview +-------- + + Libnsutils provides a small number of useful utility routines which + require platform-specific implementations. + +Requirements +------------ + + Libnsutils requires the following tools: + + + A C99 capable C compiler + + GNU make or compatible + + Pkg-config + +Compilation +----------- + + If necessary, modify the toolchain settings in the Makefile. + Invoke make: + $ make + +Verification +------------ + + To verify that the library is working, it is necessary to specify a + different makefile target than that used for normal compilation, thus: + + $ make test + +API documentation +----------------- + + Currently, there is none. However, the code is well commented and the + public API may be found in the "include" directory. The testcase sources + may also be of use in working out how to use it. + diff --git a/include/nsutils/assert.h b/include/nsutils/assert.h new file mode 100644 index 0000000..7f59f2f --- /dev/null +++ b/include/nsutils/assert.h @@ -0,0 +1,24 @@ +/* + * This file is part of LibNSUtils. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2022 Michael Drake <tlsa@netsurf-browser.org> + */ + +/** + * \file + * Static assertion macro. + */ + +#ifndef NSUTILS_ASSERT_H__ +#define NSUTILS_ASSERT_H__ + +/** Compile time assertion macro. */ +#define ns_static_assert(e) \ +{ \ + enum { \ + ns_static_assert_check = 1 / (!!(e)) \ + }; \ +} + +#endif diff --git a/include/nsutils/base64.h b/include/nsutils/base64.h index 672b69c..fb26426 100644 --- a/include/nsutils/base64.h +++ b/include/nsutils/base64.h @@ -15,6 +15,8 @@ #ifndef NSUTILS_BASE64_H_ #define NSUTILS_BASE64_H_ +#include <inttypes.h> + #include <nsutils/errors.h> /** @@ -26,7 +28,7 @@ * \param input_length The length of the source data. * \param output The buffer to recive data into, the caller must free. * \param output_length The length of data placed in \a output - * \return NSERROR_OK on success and \a output updated else error code. + * \return NSUERROR_OK on success and \a output updated else error code. */ nsuerror nsu_base64_encode_alloc(const uint8_t *input, size_t input_length, @@ -34,6 +36,56 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input, size_t *output_length); /** + * Base 64 encode data. + * + * encode source data into buffer it using the Base64 encoding. + * + * \param input The source data to encode. + * \param input_length The length of the source data. + * \param output The output buffer + * \param output_length The size of the \a output buffer on entry updated with length written on exit. + * \return NSUERROR_OK on success and \a output_length updated else error code. + */ +nsuerror nsu_base64_encode(const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length); + +/** + * Base 64 encode data. + * + * allocate a buffer and encode source data into it using the base64 URL safe + * encoding. + * + * \param input The source data to encode. + * \param input_length The length of the source data. + * \param output The buffer to recive data into, the caller must free. + * \param output_length The length of data placed in \a output + * \return NSERROR_OK on success and \a output updated else error code. + */ +nsuerror nsu_base64_encode_alloc_url(const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length); + + +/** + * Base 64 encode data. + * + * encode source data into buffer using the Base64 URL safe encoding. + * + * \param input The source data to encode. + * \param input_length The length of the source data. + * \param output The output buffer + * \param output_length The size of the \a output buffer on entry updated with length written on exit. + * \return NSUERROR_OK on success and \a output_length updated else error code. + */ +nsuerror nsu_base64_encode_url(const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length); + +/** * Base 64 decode data. * * allocate a buffer and decode source data into it using the Base64 encoding. @@ -48,5 +100,22 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input, size_t input_length, uint8_t **output, size_t *output_length); - + +/** + * Base 64 decode data. + * + * Allocate a buffer and decode source data into it using the Base64 URL safe + * encoding. + * + * \param input The source data to decode. + * \param input_length The length of the source data. + * \param output The buffer to recive data into, the caller must free. + * \param output_length The length of data placed in \a output + * \return NSERROR_OK on success and \a output updated else error code. + */ +nsuerror nsu_base64_decode_alloc_url(const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length); + #endif diff --git a/include/nsutils/endian.h b/include/nsutils/endian.h new file mode 100644 index 0000000..a15c7e2 --- /dev/null +++ b/include/nsutils/endian.h @@ -0,0 +1,71 @@ +/* + * This file is part of LibNSUtils. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org> + */ + +/** + * \file + * Endianness helper functions. + */ + +#ifndef NSUTILS_ENDIAN_H__ +#define NSUTILS_ENDIAN_H__ + +#include <inttypes.h> +#include <stdbool.h> + +/** + * Detect if the host is little endian. + * + * \return True if the host is little endian; false otherwise. + */ +static inline bool endian_host_is_le(void) +{ + const uint16_t test = 1; + + return ((const uint8_t *) &test)[0]; +} + +/** + * Swap the endianness of a 32bit value. + * + * \param val Value to swap endianness of + * \return Endian-swapped value + */ +static inline uint32_t endian_swap(uint32_t val) +{ + return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | + ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); +} + +/** + * Convert a host-endian 32bit value to its big-endian equivalent. + * + * \param host Value to convert + * \return Big endian value + */ +static inline uint32_t endian_host_to_big(uint32_t host) +{ + if (endian_host_is_le()) + return endian_swap(host); + + return host; +} + +/** + * Convert a big-endian 32bit value to its host-endian equivalent. + * + * \param host Value to convert + * \return Host endian value + */ +static inline uint32_t endian_big_to_host(uint32_t big) +{ + if (endian_host_is_le()) + return endian_swap(big); + + return big; +} + +#endif diff --git a/include/nsutils/time.h b/include/nsutils/time.h index db60914..f162b75 100644 --- a/include/nsutils/time.h +++ b/include/nsutils/time.h @@ -15,6 +15,8 @@ #ifndef NSUTILS_TIME_H_ #define NSUTILS_TIME_H_ +#include <inttypes.h> + #include <nsutils/errors.h> /** diff --git a/include/nsutils/unistd.h b/include/nsutils/unistd.h index be11382..06af226 100644 --- a/include/nsutils/unistd.h +++ b/include/nsutils/unistd.h @@ -15,6 +15,8 @@ #ifndef NSUTILS_UNISTD_H_ #define NSUTILS_UNISTD_H_ +#include <unistd.h> + /** * Perform a write operation at a specific offset * diff --git a/src/base64.c b/src/base64.c index c11364f..87752da 100644 --- a/src/base64.c +++ b/src/base64.c @@ -21,33 +21,126 @@ #include "nsutils/base64.h" -static uint8_t decoding_table[256]; -static uint8_t encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/'}; +static const uint8_t b64_decoding_table[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */ + 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63, /* 28 - 2F */ + 52, 53, 54, 55, 56, 57, 58, 59, /* 30 - 37 */ + 60, 61, 0xff, 0xff, 0xff, 64, 0xff, 0xff, /* 38 - 3F */ + 0xff, 0, 1, 2, 3, 4, 5, 6, /* 40 - 47 */ + 7, 8, 9, 10, 11, 12, 13, 14, /* 48 - 4F */ + 15, 16, 17, 18, 19, 20, 21, 22, /* 50 - 57 */ + 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff, /* 58 - 5F */ + 0xff, 26, 27, 28, 29, 30, 31, 32, /* 60 - 67 */ + 33, 34, 35, 36, 37, 38, 39, 40, /* 68 - 6F */ + 41, 42, 43, 44, 45, 46, 47, 48, /* 70 - 77 */ + 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */ +}; +static const uint8_t b64_encoding_table[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'}; +static const uint8_t b64url_decoding_table[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, /* 28 - 2F */ + 52, 53, 54, 55, 56, 57, 58, 59, /* 30 - 37 */ + 60, 61, 0xff, 0xff, 0xff, 64, 0xff, 0xff, /* 38 - 3F */ + 0xff, 0, 1, 2, 3, 4, 5, 6, /* 40 - 47 */ + 7, 8, 9, 10, 11, 12, 13, 14, /* 48 - 4F */ + 15, 16, 17, 18, 19, 20, 21, 22, /* 50 - 57 */ + 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 63, /* 58 - 5F */ + 0xff, 26, 27, 28, 29, 30, 31, 32, /* 60 - 67 */ + 33, 34, 35, 36, 37, 38, 39, 40, /* 68 - 6F */ + 41, 42, 43, 44, 45, 46, 47, 48, /* 70 - 77 */ + 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */ +}; +static const uint8_t b64url_encoding_table[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '_'}; static unsigned int mod_table[] = {0, 2, 1}; -/* exported interface documented in nsutils/base64.h */ -nsuerror nsu_base64_encode_alloc(const uint8_t *input, - size_t input_length, - uint8_t **output, - size_t *output_length) + + + +/** + * Base 64 encode data using a given encoding table. + * + * encode source data into buffer using the Base64 encoding. + * + * \param input The source data to encode. + * \param input_length The length of the source data. + * \param output The buffer to recive data into, + * \param output The output buffer + * \param output_length The size of the \a output buffer on entry updated with + * length written on exit. + * \return NSUERROR_OK on success and \a output_length updated else error code. + */ +static nsuerror +table_encode(const uint8_t *encoding_table, + const uint8_t *input, + size_t input_length, + uint8_t *encoded, + size_t *output_length) { - uint8_t *encoded; size_t encoded_len; size_t i; /* input index */ size_t j; /* output index */ encoded_len = 4 * ((input_length + 2) / 3); - encoded = malloc(encoded_len); - if (encoded == NULL) { - return NSUERROR_NOMEM; + if (encoded_len > *output_length) { + /* output buffer is too small */ + return NSUERROR_NOSPACE; } for (i = 0, j = 0; i < input_length;) { @@ -68,20 +161,151 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input, encoded[encoded_len - 1 - i] = '='; } - *output = encoded; *output_length = encoded_len; return NSUERROR_OK; } -/* exported interface documented in nsutils/base64.h */ -nsuerror nsu_base64_decode_alloc(const uint8_t *input, + +/** + * Base 64 encode data using a given encoding table. + * + * allocate a buffer and encode source data into it using the Base64 encoding. + * + * \param input The source data to encode. + * \param input_length The length of the source data. + * \param output The buffer to recive data into, the caller must free. + * \param output_length The length of data placed in \a output + * \return NSERROR_OK on success and \a output updated else error code. + */ +static nsuerror +table_encode_alloc(const uint8_t *encoding_table, + const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length) +{ + uint8_t *encoded; + size_t encoded_len; + nsuerror res; + + encoded_len = 4 * ((input_length + 2) / 3); + + encoded = malloc(encoded_len); + if (encoded == NULL) { + return NSUERROR_NOMEM; + } + + res = table_encode(encoding_table, + input, + input_length, + encoded, + &encoded_len); + if (res != NSUERROR_OK) { + free(encoded); + } else { + *output = encoded; + *output_length = encoded_len; + } + return res; +} + +/* + * standard base64 encoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_encode_alloc(const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length) +{ + return table_encode_alloc(b64_encoding_table, + input, + input_length, + output, + output_length); +} + + +/* + * url base64 encoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_encode_alloc_url(const uint8_t *input, size_t input_length, uint8_t **output, size_t *output_length) { - static bool decode_initialised = false; + return table_encode_alloc(b64url_encoding_table, + input, + input_length, + output, + output_length); +} + + +/* + * standard base64 encoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_encode(const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length) +{ + return table_encode(b64_encoding_table, + input, + input_length, + output, + output_length); +} + + +/* + * url base64 encoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_encode_url(const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length) +{ + return table_encode(b64url_encoding_table, + input, + input_length, + output, + output_length); +} + + +/** + * Base 64 decode data with a given decoding table. + * + * Allocate a buffer and decode source data into it using the Base64 decoding + * table. + * + * \param input The source data to decode. + * \param input_length The length of the source data. + * \param output The buffer to recive data into, the caller must free. + * \param output_length The length of data placed in \a output + * \return NSERROR_OK on success and \a output updated else error code. + */ +static nsuerror +base64_decode_alloc(const uint8_t *decoding_table, + const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length) +{ uint8_t *decoded; size_t decoded_len; size_t idx; @@ -89,15 +313,6 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input, uint8_t sextet[4]; int sextet_idx; - if (!decode_initialised) { - memset(decoding_table, 0xff, sizeof(decoding_table)); - for (idx = 0; idx < 64; idx++) { - decoding_table[encoding_table[idx]] = idx; - } - decoding_table['='] = 64; - decode_initialised = true; - } - decoded_len = ((input_length + 3) / 4) * 3; if (input[input_length - 1] == '=') (decoded_len)--; if (input[input_length - 2] == '=') (decoded_len)--; @@ -179,3 +394,41 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input, return NSUERROR_OK; } + + +/* + * standard base64 decoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_decode_alloc(const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length) +{ + return base64_decode_alloc(b64_decoding_table, + input, + input_length, + output, + output_length); +} + + +/* + * standard base64 decoding + * + * exported interface documented in nsutils/base64.h + */ +nsuerror +nsu_base64_decode_alloc_url(const uint8_t *input, + size_t input_length, + uint8_t **output, + size_t *output_length) +{ + return base64_decode_alloc(b64url_decoding_table, + input, + input_length, + output, + output_length); +} @@ -20,7 +20,7 @@ #include <time.h> #elif defined(__riscos) #include <oslib/os.h> -#elif defined(__MACH__) +#elif defined(__MACH__) && defined(__APPLE__) #include <mach/mach.h> #include <mach/clock.h> #include <mach/mach_time.h> @@ -51,7 +51,7 @@ nsuerror nsu_getmonotonic_ms(uint64_t *current_out) time = os_read_monotonic_time(); current = time * 10; -#elif defined(__MACH__) +#elif defined(__MACH__) && defined(__APPLE__) clock_serv_t cclock; mach_timespec_t mts; diff --git a/src/unistd.c b/src/unistd.c index 8791a44..bdedad7 100644 --- a/src/unistd.c +++ b/src/unistd.c @@ -21,7 +21,7 @@ /* exported interface documented in nsutils/unistd.h */ ssize_t nsu_pwrite(int fd, const void *buf, size_t count, off_t offset) { -#if (defined(__riscos) || defined(__amiga) || defined(_WIN32)) +#if (defined(__riscos) || defined(__amiga) || defined(_WIN32) || defined(__serenity__)) off_t sk; sk = lseek(fd, offset, SEEK_SET); @@ -53,7 +53,7 @@ ssize_t nsu_pwrite(int fd, const void *buf, size_t count, off_t offset) /* exported interface documented in nsutils/unistd.h */ ssize_t nsu_pread(int fd, void *buf, size_t count, off_t offset) { -#if (defined(__riscos) || defined(_WIN32) || (defined(__amiga) && !defined(__amigaos4__))) +#if (defined(__riscos) || defined(_WIN32) || defined(__serenity__) || (defined(__amiga) && !defined(__amigaos4__))) off_t sk; sk = lseek(fd, offset, SEEK_SET); diff --git a/test/base64.c b/test/base64.c index 7b09205..5cb8a7c 100644 --- a/test/base64.c +++ b/test/base64.c @@ -16,37 +16,65 @@ #include <stdio.h> #include <stdint.h> #include <stdlib.h> +#include <unistd.h> #include <nsutils/base64.h> int main(int argc, char**argv) { - uint8_t *buffer; - size_t buffer_len=0; - uint8_t *output; - size_t output_len; - - if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) { - return 1; - } - - if (argc == 1) { - /* encode */ - nsu_base64_encode_alloc(buffer, buffer_len, &output, &output_len); - } else if ((argv[1][0] == '-') && (argv[1][1] == 'd')) { - /* decode */ - nsu_base64_decode_alloc(buffer, buffer_len, &output, &output_len); - } else { - fprintf(stderr, "Usage: %s [-d]\n", argv[0]); - return 1; - } - - if (output != NULL) { - printf("%.*s", (int)output_len, output); - free(output); - } - - free(buffer); - - return 0; + uint8_t *buffer; + size_t buffer_len=0; + uint8_t *output; + size_t output_len; + int opt; + int decode = 0; + int url = 0; + + + while ((opt = getopt(argc, argv, "du")) != -1) { + switch (opt) { + case 'd': + decode = 1; + break; + case 'u': + url = 1; + break; + + default: /* '?' */ + fprintf(stderr, "Usage: %s [-d] [-u]\n", argv[0]); + exit(EXIT_FAILURE); + + } + } + + if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) { + return 1; + } + + + if (decode) { + /* decode */ + if (url) { + nsu_base64_decode_alloc_url(buffer, buffer_len, &output, &output_len); + } else { + + nsu_base64_decode_alloc(buffer, buffer_len, &output, &output_len); + } + } else { + /* encode */ + if (url) { + nsu_base64_encode_alloc_url(buffer, buffer_len, &output, &output_len); + } else { + nsu_base64_encode_alloc(buffer, buffer_len, &output, &output_len); + } + } + + if (output != NULL) { + printf("%.*s", (int)output_len, output); + free(output); + } + + free(buffer); + + return 0; } diff --git a/test/runtest.sh b/test/runtest.sh index efcb79f..9f02e1c 100755 --- a/test/runtest.sh +++ b/test/runtest.sh @@ -5,30 +5,70 @@ b64enctst() { ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 ) if [ "${ENC}" != "${2}" ];then - echo "Base64 encode error ${ENC} != ${2}" + echo "Base64 encode error '${ENC}' != '${2}'" exit 2 - fi + fi } b64dectst() { DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d ) if [ "${DEC}" != "$2" ];then - echo "Base64 decode error ${DEC} != $2" + echo "Base64 decode error '${DEC}' != '$2'" exit 3 - fi + fi } -b64enctst 'f' 'Zg==' -b64enctst 'fo' 'Zm8=' -b64enctst 'foo' 'Zm9v' -b64enctst 'foob' 'Zm9vYg==' -b64enctst 'fooba' 'Zm9vYmE=' +b64urlenctst() +{ + ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 -u ) + if [ "${ENC}" != "${2}" ];then + echo "Base64 url encode error '${ENC}' != '${2}'" + exit 2 + fi +} + +b64urldectst() +{ + DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d -u ) + if [ "${DEC}" != "$2" ];then + echo "Base64 url decode error '${DEC}' != '$2'" + exit 3 + fi +} + +b64enctst 'f' 'Zg==' +b64enctst 'fo' 'Zm8=' +b64enctst 'foo' 'Zm9v' +b64enctst ' >' 'ICA+' +b64enctst ' ?' 'ICA/' +b64enctst 'foob' 'Zm9vYg==' +b64enctst 'fooba' 'Zm9vYmE=' b64enctst 'foobar' 'Zm9vYmFy' -b64dectst 'Zg==' 'f' -b64dectst 'Zm8=' 'fo' -b64dectst 'Zm9v' 'foo' +b64dectst 'Zg==' 'f' +b64dectst 'Zm8=' 'fo' +b64dectst 'Zm9v' 'foo' +b64dectst 'ICA+' ' >' +b64dectst 'ICA/' ' ?' b64dectst 'Zm9vYg==' 'foob' b64dectst 'Zm9vYmE=' 'fooba' b64dectst 'Zm9vYmFy' 'foobar' + +b64urlenctst 'f' 'Zg==' +b64urlenctst 'fo' 'Zm8=' +b64urlenctst 'foo' 'Zm9v' +b64urlenctst ' >' 'ICA-' +b64urlenctst ' ?' 'ICA_' +b64urlenctst 'foob' 'Zm9vYg==' +b64urlenctst 'fooba' 'Zm9vYmE=' +b64urlenctst 'foobar' 'Zm9vYmFy' + +b64urldectst 'Zg==' 'f' +b64urldectst 'Zm8=' 'fo' +b64urldectst 'Zm9v' 'foo' +b64urldectst 'ICA-' ' >' +b64urldectst 'ICA_' ' ?' +b64urldectst 'Zm9vYg==' 'foob' +b64urldectst 'Zm9vYmE=' 'fooba' +b64urldectst 'Zm9vYmFy' 'foobar' |