/*******************************************************************************
* This file is part of the Incubed project.
* Sources: https://github.com/blockchainsllc/in3
*
* Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC
*
*
* COMMERCIAL LICENSE USAGE
*
* Licensees holding a valid commercial license may use this file in accordance
* with the commercial license agreement provided with the Software or, alternatively,
* in accordance with the terms contained in a written agreement between you and
* slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further
* information please contact slock.it at in3@slock.it.
*
* Alternatively, this file may be used under the AGPL license as follows:
*
* AGPL LICENSE USAGE
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Affero General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
* [Permissions of this strong copyleft license are conditioned on making available
* complete source code of licensed works and modifications, which include larger
* works using a licensed work, under the same license. Copyright and license notices
* must be preserved. Contributors provide an express grant of patent rights.]
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see .
*******************************************************************************/
// @PUBLIC_HEADER
/** @file
* util helper on byte arrays.
* */
#ifndef BYTES_H
#define BYTES_H
#ifdef __cplusplus
extern "C" {
#endif
#include "mem.h"
#include
#include
#include
#include
/** creates a new bytes_builder with a initial size of 32 bytes */
#define bb_new() bb_newl(32)
#define bb_read(_bb_, _i_, _vptr_) bb_readl((_bb_), (_i_), (_vptr_), sizeof(*_vptr_))
#define bb_read_next(_bb_, _iptr_, _vptr_) \
do { \
size_t _l_ = sizeof(*_vptr_); \
bb_readl((_bb_), *(_iptr_), (_vptr_), _l_); \
*(_iptr_) += _l_; \
} while (0)
#define bb_readl(_bb_, _i_, _vptr_, _l_) memcpy((_vptr_), (_bb_)->b.data + (_i_), _l_)
#define b_read(_b_, _i_, _vptr_) b_readl((_b_), (_i_), _vptr_, sizeof(*_vptr_))
#define b_readl(_b_, _i_, _vptr_, _l_) memcpy(_vptr_, (_b_)->data + (_i_), (_l_))
typedef uint8_t address_t[20]; /**< pointer to a 20byte address */
typedef uint8_t bytes32_t[32]; /**< pointer to a 32byte word */
#ifdef ESP_IDF
typedef uint8_t wlen_t; /**< number of bytes within a word (min 1byte but usually a uint) */
#else
typedef uint_fast8_t wlen_t; /**< number of bytes within a word (min 1byte but usually a uint) */
#endif
/** a byte array */
typedef struct bytes {
uint8_t* data; /**< the byte-data */
uint32_t len; /**< the length of the array ion bytes */
} bytes_t;
/** a byte-buffer to attach byte-functions. */
typedef struct {
size_t bsize; /**< size of the currently allocated bytes */
bytes_t b; /**< the bytes struct */
} bytes_builder_t;
#define NULL_BYTES ((bytes_t){0}) /**< empty bytes as struct */
RETURNS_NONULL bytes_t* b_new(const uint8_t* data, uint32_t len); /**< allocates a new byte array with 0 filled */
NONULL uint8_t* b_get_data(const bytes_t* b); /**< gets the data field from an input byte array */
NONULL uint32_t b_get_len(const bytes_t* b); /**< gets the len field from an input byte array */
NONULL void b_print(const bytes_t* a); /**< prints a the bytes as hex to stdout */
NONULL void ba_print(const uint8_t* a, size_t l); /**< prints a the bytes as hex to stdout */
NONULL int b_cmp(const bytes_t* a, const bytes_t* b); /**< compares 2 byte arrays and returns 1 for equal and 0 for not equal*/
int bytes_cmp(const bytes_t a, const bytes_t b); /**< compares 2 byte arrays and returns 1 for equal and 0 for not equal*/
void b_free(bytes_t* a); /**< frees the data */
bytes_t b_concat(int cnt, ...); /**< duplicates the content of bytes*/
NONULL bytes_t* b_dup(const bytes_t* a); /**< clones a byte array*/
NONULL bytes_t bytes_dup(const bytes_t a); /**< clones a byte array*/
NONULL uint8_t b_read_byte(bytes_t* b, size_t* pos); /**< reads a byte on the current position and updates the pos afterwards. */
NONULL uint32_t b_read_int(bytes_t* b, size_t* pos); /**< reads a integer on the current position and updates the pos afterwards. */
NONULL uint64_t b_read_long(bytes_t* b, size_t* pos); /**< reads a long on the current position and updates the pos afterwards. */
NONULL char* b_new_chars(bytes_t* b, size_t* pos); /**< creates a new string (needs to be freed) on the current position and updates the pos afterwards. */
NONULL bytes_t* b_new_fixed_bytes(bytes_t* b, size_t* pos, int len); /**< reads bytes with a fixed length on the current position and updates the pos afterwards. */
bytes_builder_t* bb_newl(size_t l); /**< creates a new bytes_builder */
NONULL void bb_free(bytes_builder_t* bb); /**< frees a bytebuilder and its content. */
NONULL int bb_check_size(bytes_builder_t* bb, size_t len); /**< internal helper to increase the buffer if needed */
NONULL void bb_write_chars(bytes_builder_t* bb, char* c, int len); /**< writes a string to the builder. */
NONULL void bb_write_dyn_bytes(bytes_builder_t* bb, const bytes_t* src); /**< writes bytes to the builder with a prefixed length. */
NONULL void bb_write_fixed_bytes(bytes_builder_t* bb, const bytes_t* src); /**< writes fixed bytes to the builder. */
NONULL void bb_write_int(bytes_builder_t* bb, uint32_t val); /**< writes a ineteger to the builder. */
NONULL void bb_write_long(bytes_builder_t* bb, uint64_t val); /**< writes s long to the builder. */
NONULL void bb_write_long_be(bytes_builder_t* bb, uint64_t val, int len); /**< writes any integer value with the given length of bytes */
NONULL void bb_write_byte(bytes_builder_t* bb, uint8_t val); /**< writes a single byte to the builder. */
NONULL void bb_write_raw_bytes(bytes_builder_t* bb, void* ptr, size_t len); /**< writes the bytes to the builder. */
NONULL void bb_clear(bytes_builder_t* bb); /**< resets the content of the builder. */
NONULL void bb_replace(bytes_builder_t* bb, int offset, int delete_len, uint8_t* data, int data_len); /**< replaces or deletes a part of the content. */
RETURNS_NONULL NONULL bytes_t* bb_move_to_bytes(bytes_builder_t* bb); /**< frees the builder and moves the content in a newly created bytes struct (which needs to be freed later). */
NONULL uint64_t bb_read_long(bytes_builder_t* bb, size_t* i); /**< reads a long from the builder */
NONULL uint32_t bb_read_int(bytes_builder_t* bb, size_t* i); /**< reads a int from the builder */
static inline bytes_t bytes(uint8_t* a, uint32_t len) { return (bytes_t){.data = a, .len = len}; } /**< converts the given bytes to a bytes struct */
bytes_t cloned_bytes(bytes_t data); /**< cloned the passed data*/
NONULL static inline void b_optimize_len(bytes_t* b) { /**< changed the data and len to remove leading 0-bytes */
while (b->len > 1 && *b->data == 0) {
b->data++;
b->len--;
}
}
static inline int b_compare(bytes_t a, bytes_t b) {
return (a.len == b.len)
? memcmp(a.data, b.data, a.len)
: ((int) a.len) - ((int) b.len);
}
#define b_to_stack(d) \
{ \
bytes_t o = d; \
d.data = alloca(d.len); \
memcpy(d.data, o.data, o.len); \
_free(o.data); \
} /**< converts bytes from heap to stack */
#ifdef __cplusplus
}
#endif
#endif