blind reformat all files
This commit is contained in:
@@ -33,11 +33,11 @@
|
|||||||
#define SC_ARRAY_H
|
#define SC_ARRAY_H
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define SC_ARRAY_VERSION "2.0.0"
|
#define SC_ARRAY_VERSION "2.0.0"
|
||||||
|
|
||||||
@@ -98,8 +98,7 @@
|
|||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
_cap = (a)->cap == 0 ? 8 : (a)->cap * 2; \
|
_cap = (a)->cap == 0 ? 8 : (a)->cap * 2; \
|
||||||
_p = sc_array_realloc((a)->elems, \
|
_p = sc_array_realloc((a)->elems, _cap * sizeof(*((a)->elems))); \
|
||||||
_cap * sizeof(*((a)->elems))); \
|
|
||||||
if (_p == NULL) { \
|
if (_p == NULL) { \
|
||||||
(a)->oom = true; \
|
(a)->oom = true; \
|
||||||
break; \
|
break; \
|
||||||
|
|||||||
@@ -7,5 +7,4 @@ typedef struct {
|
|||||||
const char *command;
|
const char *command;
|
||||||
} CompileCommand;
|
} CompileCommand;
|
||||||
|
|
||||||
|
|
||||||
#endif // COMPILATION_H_
|
#endif // COMPILATION_H_
|
||||||
|
|||||||
10
src/memory.c
10
src/memory.c
@@ -14,14 +14,16 @@ HiloadResult memory_find_pointer(uptr ptr,
|
|||||||
size_t *index) {
|
size_t *index) {
|
||||||
for (size_t i = 0; i < sc_array_size(regions); i++) {
|
for (size_t i = 0; i < sc_array_size(regions); i++) {
|
||||||
uptr start = regions->elems[i].region_start;
|
uptr start = regions->elems[i].region_start;
|
||||||
// we assume a sorted region by start address, so we can do a quick discard here.
|
// we assume a sorted region by start address, so we can do a quick discard
|
||||||
// very useful for relative vs absolute address checks
|
// here. very useful for relative vs absolute address checks
|
||||||
if (ptr < start) return HILOAD_FAIL;
|
if (ptr < start)
|
||||||
|
return HILOAD_FAIL;
|
||||||
uptr end = regions->elems[i].region_end;
|
uptr end = regions->elems[i].region_end;
|
||||||
if (ptr_in_range(ptr, start, end)) {
|
if (ptr_in_range(ptr, start, end)) {
|
||||||
if (index)
|
if (index)
|
||||||
*index = i;
|
*index = i;
|
||||||
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n", ptr, i, start, end);
|
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n",
|
||||||
|
ptr, i, start, end);
|
||||||
return HILOAD_OK;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/memory.h
11
src/memory.h
@@ -1,9 +1,9 @@
|
|||||||
#ifndef MEMORY_H_
|
#ifndef MEMORY_H_
|
||||||
#define MEMORY_H_
|
#define MEMORY_H_
|
||||||
|
|
||||||
|
#include "array.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "array.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -24,14 +24,15 @@ typedef struct {
|
|||||||
const char *pathname;
|
const char *pathname;
|
||||||
} MemoryRegion;
|
} MemoryRegion;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sc_array_def(MemoryRegion, memreg);
|
sc_array_def(MemoryRegion, memreg);
|
||||||
|
|
||||||
/* A pointer that can be used to place the memory regions into. Clears regions before use, but uses the same buffer. */
|
/* A pointer that can be used to place the memory regions into. Clears regions
|
||||||
|
* before use, but uses the same buffer. */
|
||||||
HiloadResult read_memory_maps_self(struct sc_array_memreg *regions);
|
HiloadResult read_memory_maps_self(struct sc_array_memreg *regions);
|
||||||
|
|
||||||
/* Return index the pointer is found in */
|
/* Return index the pointer is found in */
|
||||||
HiloadResult memory_find_pointer(uptr ptr, struct sc_array_memreg* const regions, size_t *index);
|
HiloadResult memory_find_pointer(uptr ptr,
|
||||||
|
struct sc_array_memreg *const regions,
|
||||||
|
size_t *index);
|
||||||
|
|
||||||
#endif // MEMORY_H_
|
#endif // MEMORY_H_
|
||||||
|
|||||||
297
src/str.c
297
src/str.c
@@ -35,33 +35,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
// append to destination and return the end pointer
|
// append to destination and return the end pointer
|
||||||
static inline
|
static inline void *mem_append(void *dest, const void *src, const size_t n) {
|
||||||
void* mem_append(void* dest, const void* src, const size_t n)
|
|
||||||
{
|
|
||||||
return memcpy(dest, src, n) + n;
|
return memcpy(dest, src, n) + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string deallocation
|
// string deallocation
|
||||||
void str_free(const str s)
|
void str_free(const str s) {
|
||||||
{
|
|
||||||
if (str_is_owner(s))
|
if (str_is_owner(s))
|
||||||
free((void *)s.ptr);
|
free((void *)s.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// version of str_free() for str_auto macro
|
// version of str_free() for str_auto macro
|
||||||
void str_free_auto(const str* const ps)
|
void str_free_auto(const str *const ps) {
|
||||||
{
|
|
||||||
if (ps)
|
if (ps)
|
||||||
str_free(*ps);
|
str_free(*ps);
|
||||||
}
|
}
|
||||||
@@ -70,25 +66,30 @@ void str_free_auto(const str* const ps)
|
|||||||
#define ALLOC(n) \
|
#define ALLOC(n) \
|
||||||
({ \
|
({ \
|
||||||
void *const ___p = malloc(n); \
|
void *const ___p = malloc(n); \
|
||||||
if(!___p) return ENOMEM; \
|
if (!___p) \
|
||||||
|
return ENOMEM; \
|
||||||
___p; \
|
___p; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define REALLOC(p, n) \
|
#define REALLOC(p, n) \
|
||||||
({ \
|
({ \
|
||||||
void *const ___p = realloc((p), (n)); \
|
void *const ___p = realloc((p), (n)); \
|
||||||
if(!___p) return ENOMEM; \
|
if (!___p) \
|
||||||
|
return ENOMEM; \
|
||||||
___p; \
|
___p; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// errno checker
|
// errno checker
|
||||||
#define RETURN_ON_ERROR(expr) \
|
#define RETURN_ON_ERROR(expr) \
|
||||||
while((expr) < 0) do { const int __err = errno; if(__err != EINTR) return __err; } while(0)
|
while ((expr) < 0) \
|
||||||
|
do { \
|
||||||
|
const int __err = errno; \
|
||||||
|
if (__err != EINTR) \
|
||||||
|
return __err; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
// swap
|
// swap
|
||||||
void str_swap(str* const s1, str* const s2)
|
void str_swap(str *const s1, str *const s2) {
|
||||||
{
|
|
||||||
const str tmp = *s1;
|
const str tmp = *s1;
|
||||||
|
|
||||||
*s1 = *s2;
|
*s1 = *s2;
|
||||||
@@ -98,10 +99,10 @@ void str_swap(str* const s1, str* const s2)
|
|||||||
// empty string
|
// empty string
|
||||||
const char *const str_empty_string = "";
|
const char *const str_empty_string = "";
|
||||||
|
|
||||||
// string comparison ---------------------------------------------------------------------
|
// string comparison
|
||||||
// compare two strings lexicographically
|
// --------------------------------------------------------------------- compare
|
||||||
int str_cmp(const str s1, const str s2)
|
// two strings lexicographically
|
||||||
{
|
int str_cmp(const str s1, const str s2) {
|
||||||
const size_t n1 = str_len(s1), n2 = str_len(s2);
|
const size_t n1 = str_len(s1), n2 = str_len(s2);
|
||||||
|
|
||||||
// either string may be missing a null terminator, hence "memcmp"
|
// either string may be missing a null terminator, hence "memcmp"
|
||||||
@@ -114,8 +115,7 @@ int str_cmp(const str s1, const str s2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// case-insensitive comparison
|
// case-insensitive comparison
|
||||||
int str_cmp_ci(const str s1, const str s2)
|
int str_cmp_ci(const str s1, const str s2) {
|
||||||
{
|
|
||||||
const size_t n1 = str_len(s1), n2 = str_len(s2);
|
const size_t n1 = str_len(s1), n2 = str_len(s2);
|
||||||
|
|
||||||
// either string may be missing a null terminator, hence "strNcasecmp"
|
// either string may be missing a null terminator, hence "strNcasecmp"
|
||||||
@@ -128,43 +128,38 @@ int str_cmp_ci(const str s1, const str s2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test for prefix
|
// test for prefix
|
||||||
bool str_has_prefix(const str s, const str prefix)
|
bool str_has_prefix(const str s, const str prefix) {
|
||||||
{
|
|
||||||
const size_t n = str_len(prefix);
|
const size_t n = str_len(prefix);
|
||||||
|
|
||||||
return (n == 0)
|
return (n == 0) ||
|
||||||
|| (str_len(s) >= n && memcmp(str_ptr(s), str_ptr(prefix), n) == 0);
|
(str_len(s) >= n && memcmp(str_ptr(s), str_ptr(prefix), n) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for suffix
|
// test for suffix
|
||||||
bool str_has_suffix(const str s, const str suffix)
|
bool str_has_suffix(const str s, const str suffix) {
|
||||||
{
|
|
||||||
const size_t n = str_len(suffix);
|
const size_t n = str_len(suffix);
|
||||||
|
|
||||||
return (n == 0)
|
return (n == 0) ||
|
||||||
|| (str_len(s) >= n && memcmp(str_end(s) - n, str_ptr(suffix), n) == 0);
|
(str_len(s) >= n && memcmp(str_end(s) - n, str_ptr(suffix), n) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// string constructors -----------------------------------------------------------------
|
// string constructors
|
||||||
// create a reference to the given range of chars
|
// ----------------------------------------------------------------- create a
|
||||||
str str_ref_chars(const char* const s, const size_t n)
|
// reference to the given range of chars
|
||||||
{
|
str str_ref_chars(const char *const s, const size_t n) {
|
||||||
return (s && n > 0) ? ((str){s, str_ref_info(n)}) : str_null;
|
return (s && n > 0) ? ((str){s, str_ref_info(n)}) : str_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
str str_ref_from_ptr(const char* const s)
|
str str_ref_from_ptr(const char *const s) {
|
||||||
{
|
|
||||||
return s ? str_ref_chars(s, strlen(s)) : str_null;
|
return s ? str_ref_chars(s, strlen(s)) : str_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// take ownership of the given range of chars
|
// take ownership of the given range of chars
|
||||||
str str_acquire_chars(const char* const s, const size_t n)
|
str str_acquire_chars(const char *const s, const size_t n) {
|
||||||
{
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return str_null;
|
return str_null;
|
||||||
|
|
||||||
if(n == 0)
|
if (n == 0) {
|
||||||
{
|
|
||||||
free((void *)s);
|
free((void *)s);
|
||||||
return str_null;
|
return str_null;
|
||||||
}
|
}
|
||||||
@@ -173,20 +168,17 @@ str str_acquire_chars(const char* const s, const size_t n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// take ownership of the given C string
|
// take ownership of the given C string
|
||||||
str str_acquire(const char* const s)
|
str str_acquire(const char *const s) {
|
||||||
{
|
|
||||||
return s ? str_acquire_chars(s, strlen(s)) : str_null;
|
return s ? str_acquire_chars(s, strlen(s)) : str_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate a copy of the given string
|
// allocate a copy of the given string
|
||||||
int str_dup_impl(str* const dest, const str s)
|
int str_dup_impl(str *const dest, const str s) {
|
||||||
{
|
|
||||||
const size_t n = str_len(s);
|
const size_t n = str_len(s);
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
char *const p = memcpy(ALLOC(n + 1), str_ptr(s), n);
|
char *const p = memcpy(ALLOC(n + 1), str_ptr(s), n);
|
||||||
|
|
||||||
p[n] = 0;
|
p[n] = 0;
|
||||||
@@ -200,9 +192,7 @@ int str_dup_impl(str* const dest, const str s)
|
|||||||
#define STR_MAX_FILE_SIZE (64 * 1024 * 1024 - 1)
|
#define STR_MAX_FILE_SIZE (64 * 1024 * 1024 - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static
|
static int get_file_size(const int fd, off_t *const size) {
|
||||||
int get_file_size(const int fd, off_t* const size)
|
|
||||||
{
|
|
||||||
// stat the file
|
// stat the file
|
||||||
struct stat info;
|
struct stat info;
|
||||||
|
|
||||||
@@ -211,8 +201,7 @@ int get_file_size(const int fd, off_t* const size)
|
|||||||
*size = info.st_size;
|
*size = info.st_size;
|
||||||
|
|
||||||
// only regular files are allowed
|
// only regular files are allowed
|
||||||
switch(info.st_mode & S_IFMT)
|
switch (info.st_mode & S_IFMT) {
|
||||||
{
|
|
||||||
case S_IFREG:
|
case S_IFREG:
|
||||||
return (info.st_size > STR_MAX_FILE_SIZE) ? EFBIG : 0;
|
return (info.st_size > STR_MAX_FILE_SIZE) ? EFBIG : 0;
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
@@ -222,14 +211,11 @@ int get_file_size(const int fd, off_t* const size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int read_from_fd(const int fd, void *p, off_t *const psize) {
|
||||||
int read_from_fd(const int fd, void* p, off_t* const psize)
|
|
||||||
{
|
|
||||||
const void *const end = p + *psize;
|
const void *const end = p + *psize;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
RETURN_ON_ERROR(n = read(fd, p, end - p));
|
RETURN_ON_ERROR(n = read(fd, p, end - p));
|
||||||
|
|
||||||
p += n;
|
p += n;
|
||||||
@@ -239,16 +225,13 @@ int read_from_fd(const int fd, void* p, off_t* const psize)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int read_from_fd_cont(const int fd, void *p, off_t *const psize) {
|
||||||
int read_from_fd_cont(const int fd, void* p, off_t* const psize)
|
|
||||||
{
|
|
||||||
const void *end = p + *psize;
|
const void *end = p + *psize;
|
||||||
void *buf = p;
|
void *buf = p;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
ssize_t nread = 0;
|
ssize_t nread = 0;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
RETURN_ON_ERROR(n = read(fd, p, end - p));
|
RETURN_ON_ERROR(n = read(fd, p, end - p));
|
||||||
|
|
||||||
p += n;
|
p += n;
|
||||||
@@ -267,12 +250,8 @@ int read_from_fd_cont(const int fd, void* p, off_t* const psize)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int str_from_fd(const int fd, const off_t size, str *const dest) {
|
||||||
static
|
if (size == 0) {
|
||||||
int str_from_fd(const int fd, const off_t size, str* const dest)
|
|
||||||
{
|
|
||||||
if(size == 0)
|
|
||||||
{
|
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -281,25 +260,21 @@ int str_from_fd(const int fd, const off_t size, str* const dest)
|
|||||||
off_t n = size;
|
off_t n = size;
|
||||||
const int err = read_from_fd(fd, buff, &n);
|
const int err = read_from_fd(fd, buff, &n);
|
||||||
|
|
||||||
if(err != 0)
|
if (err != 0) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n == 0)
|
if (n == 0) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n < size)
|
if (n < size) {
|
||||||
{
|
|
||||||
char *const p = realloc(buff, n + 1);
|
char *const p = realloc(buff, n + 1);
|
||||||
|
|
||||||
if(!p)
|
if (!p) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
@@ -312,34 +287,28 @@ int str_from_fd(const int fd, const off_t size, str* const dest)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int str_from_stream_cont(const int fd, str *const dest, int *nmax) {
|
||||||
int str_from_stream_cont(const int fd, str* const dest, int *nmax)
|
|
||||||
{
|
|
||||||
const size_t start_size = 8192;
|
const size_t start_size = 8192;
|
||||||
|
|
||||||
char *buff = ALLOC(start_size + 1);
|
char *buff = ALLOC(start_size + 1);
|
||||||
off_t n = start_size;
|
off_t n = start_size;
|
||||||
const int err = read_from_fd_cont(fd, buff, &n);
|
const int err = read_from_fd_cont(fd, buff, &n);
|
||||||
|
|
||||||
if(err != 0)
|
if (err != 0) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n == 0)
|
if (n == 0) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n < start_size)
|
if (n < start_size) {
|
||||||
{
|
|
||||||
char *const p = realloc(buff, n + 1);
|
char *const p = realloc(buff, n + 1);
|
||||||
|
|
||||||
if(!p)
|
if (!p) {
|
||||||
{
|
|
||||||
free(buff);
|
free(buff);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
@@ -352,8 +321,7 @@ int str_from_stream_cont(const int fd, str* const dest, int *nmax)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_from_file(str* const dest, const char* const file_name)
|
int str_from_file(str *const dest, const char *const file_name) {
|
||||||
{
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
RETURN_ON_ERROR(fd = open(file_name, O_CLOEXEC | O_RDONLY));
|
RETURN_ON_ERROR(fd = open(file_name, O_CLOEXEC | O_RDONLY));
|
||||||
@@ -368,8 +336,7 @@ int str_from_file(str* const dest, const char* const file_name)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_from_stream(str* const dest, const char* const file_name, int *nread)
|
int str_from_stream(str *const dest, const char *const file_name, int *nread) {
|
||||||
{
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
RETURN_ON_ERROR(fd = open(file_name, O_CLOEXEC | O_RDONLY));
|
RETURN_ON_ERROR(fd = open(file_name, O_CLOEXEC | O_RDONLY));
|
||||||
@@ -390,17 +357,14 @@ int str_from_stream(str* const dest, const char* const file_name, int *nread)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string composition -----------------------------------------------------------------------
|
// string composition
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
// append string
|
// append string
|
||||||
static inline
|
static inline char *append_str(char *p, const str s) {
|
||||||
char* append_str(char* p, const str s)
|
|
||||||
{
|
|
||||||
return mem_append(p, str_ptr(s), str_len(s));
|
return mem_append(p, str_ptr(s), str_len(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static size_t total_length(const str *src, size_t count) {
|
||||||
size_t total_length(const str* src, size_t count)
|
|
||||||
{
|
|
||||||
size_t sum = 0;
|
size_t sum = 0;
|
||||||
|
|
||||||
for (; count > 0; --count)
|
for (; count > 0; --count)
|
||||||
@@ -410,10 +374,8 @@ size_t total_length(const str* src, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// concatenate strings
|
// concatenate strings
|
||||||
int str_cat_range_impl(str* const dest, const str* src, size_t count)
|
int str_cat_range_impl(str *const dest, const str *src, size_t count) {
|
||||||
{
|
if (!src) {
|
||||||
if(!src)
|
|
||||||
{
|
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -421,8 +383,7 @@ int str_cat_range_impl(str* const dest, const str* src, size_t count)
|
|||||||
// calculate total length
|
// calculate total length
|
||||||
const size_t num = total_length(src, count);
|
const size_t num = total_length(src, count);
|
||||||
|
|
||||||
if(num == 0)
|
if (num == 0) {
|
||||||
{
|
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -443,13 +404,11 @@ int str_cat_range_impl(str* const dest, const str* src, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writing to file descriptor
|
// writing to file descriptor
|
||||||
int str_cpy_to_fd(const int fd, const str s)
|
int str_cpy_to_fd(const int fd, const str s) {
|
||||||
{
|
|
||||||
size_t n = str_len(s);
|
size_t n = str_len(s);
|
||||||
const void *p = str_ptr(s);
|
const void *p = str_ptr(s);
|
||||||
|
|
||||||
while(n > 0)
|
while (n > 0) {
|
||||||
{
|
|
||||||
ssize_t m;
|
ssize_t m;
|
||||||
|
|
||||||
RETURN_ON_ERROR(m = write(fd, p, n));
|
RETURN_ON_ERROR(m = write(fd, p, n));
|
||||||
@@ -462,28 +421,22 @@ int str_cpy_to_fd(const int fd, const str s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writing to byte stream
|
// writing to byte stream
|
||||||
int str_cpy_to_stream(FILE* const stream, const str s)
|
int str_cpy_to_stream(FILE *const stream, const str s) {
|
||||||
{
|
|
||||||
const size_t n = str_len(s);
|
const size_t n = str_len(s);
|
||||||
|
|
||||||
return (n > 0 && fwrite(str_ptr(s), 1, n, stream) < n) ? EIO : 0;
|
return (n > 0 && fwrite(str_ptr(s), 1, n, stream) < n) ? EIO : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write iovec
|
// write iovec
|
||||||
static
|
static int write_iovec(const int fd, struct iovec *pv, unsigned nv) {
|
||||||
int write_iovec(const int fd, struct iovec* pv, unsigned nv)
|
while (nv > 0) {
|
||||||
{
|
|
||||||
while(nv > 0)
|
|
||||||
{
|
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
RETURN_ON_ERROR(n = writev(fd, pv, nv));
|
RETURN_ON_ERROR(n = writev(fd, pv, nv));
|
||||||
|
|
||||||
// discard items already written
|
// discard items already written
|
||||||
for(; nv > 0; ++pv, --nv)
|
for (; nv > 0; ++pv, --nv) {
|
||||||
{
|
if (n < (ssize_t)pv->iov_len) {
|
||||||
if(n < (ssize_t)pv->iov_len)
|
|
||||||
{
|
|
||||||
pv->iov_base += n;
|
pv->iov_base += n;
|
||||||
pv->iov_len -= n;
|
pv->iov_len -= n;
|
||||||
break;
|
break;
|
||||||
@@ -497,29 +450,23 @@ int write_iovec(const int fd, struct iovec* pv, unsigned nv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// concatenate to file descriptor
|
// concatenate to file descriptor
|
||||||
static
|
static struct iovec *vec_append(struct iovec *const pv, const str s) {
|
||||||
struct iovec* vec_append(struct iovec* const pv, const str s)
|
|
||||||
{
|
|
||||||
*pv = (struct iovec){(void *)str_ptr(s), str_len(s)};
|
*pv = (struct iovec){(void *)str_ptr(s), str_len(s)};
|
||||||
|
|
||||||
return pv + 1;
|
return pv + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static struct iovec *vec_append_nonempty(struct iovec *const pv, const str s) {
|
||||||
struct iovec* vec_append_nonempty(struct iovec* const pv, const str s)
|
|
||||||
{
|
|
||||||
return str_is_empty(s) ? pv : vec_append(pv, s);
|
return str_is_empty(s) ? pv : vec_append(pv, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_cat_range_to_fd(const int fd, const str* src, size_t count)
|
int str_cat_range_to_fd(const int fd, const str *src, size_t count) {
|
||||||
{
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
struct iovec v[IOV_MAX];
|
struct iovec v[IOV_MAX];
|
||||||
|
|
||||||
while(count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
struct iovec *p = vec_append_nonempty(v, *src++);
|
struct iovec *p = vec_append_nonempty(v, *src++);
|
||||||
|
|
||||||
while (--count > 0 && p < v + IOV_MAX)
|
while (--count > 0 && p < v + IOV_MAX)
|
||||||
@@ -539,8 +486,7 @@ int str_cat_range_to_fd(const int fd, const str* src, size_t count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_cat_range_to_stream(FILE* const stream, const str* src, size_t count)
|
int str_cat_range_to_stream(FILE *const stream, const str *src, size_t count) {
|
||||||
{
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -553,14 +499,13 @@ int str_cat_range_to_stream(FILE* const stream, const str* src, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// join strings
|
// join strings
|
||||||
int str_join_range_impl(str* const dest, const str sep, const str* src, size_t count)
|
int str_join_range_impl(str *const dest, const str sep, const str *src,
|
||||||
{
|
size_t count) {
|
||||||
// test for simple cases
|
// test for simple cases
|
||||||
if (str_is_empty(sep))
|
if (str_is_empty(sep))
|
||||||
return str_cat_range(dest, src, count);
|
return str_cat_range(dest, src, count);
|
||||||
|
|
||||||
if(!src || count == 0)
|
if (!src || count == 0) {
|
||||||
{
|
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -586,8 +531,8 @@ int str_join_range_impl(str* const dest, const str sep, const str* src, size_t c
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_join_range_to_fd(const int fd, const str sep, const str* src, size_t count)
|
int str_join_range_to_fd(const int fd, const str sep, const str *src,
|
||||||
{
|
size_t count) {
|
||||||
if (str_is_empty(sep))
|
if (str_is_empty(sep))
|
||||||
return str_cat_range(fd, src, count);
|
return str_cat_range(fd, src, count);
|
||||||
|
|
||||||
@@ -601,8 +546,7 @@ int str_join_range_to_fd(const int fd, const str sep, const str* src, size_t cou
|
|||||||
|
|
||||||
struct iovec *p = vec_append_nonempty(v, *src++);
|
struct iovec *p = vec_append_nonempty(v, *src++);
|
||||||
|
|
||||||
for(--count; count > 0; p = v)
|
for (--count; count > 0; p = v) {
|
||||||
{
|
|
||||||
p = vec_append_nonempty(vec_append(p, sep), *src++);
|
p = vec_append_nonempty(vec_append(p, sep), *src++);
|
||||||
|
|
||||||
while (--count > 0 && p < v + IOV_MAX - 1)
|
while (--count > 0 && p < v + IOV_MAX - 1)
|
||||||
@@ -622,8 +566,8 @@ int str_join_range_to_fd(const int fd, const str sep, const str* src, size_t cou
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_join_range_to_stream(FILE* const stream, const str sep, const str* src, size_t count)
|
int str_join_range_to_stream(FILE *const stream, const str sep, const str *src,
|
||||||
{
|
size_t count) {
|
||||||
if (str_is_empty(sep))
|
if (str_is_empty(sep))
|
||||||
return str_cat_range(stream, src, count);
|
return str_cat_range(stream, src, count);
|
||||||
|
|
||||||
@@ -638,23 +582,21 @@ int str_join_range_to_stream(FILE* const stream, const str sep, const str* src,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// searching and sorting --------------------------------------------------------------------
|
// searching and sorting
|
||||||
// string partitioning
|
// -------------------------------------------------------------------- string
|
||||||
bool str_partition(const str src, const str patt, str* const prefix, str* const suffix)
|
// partitioning
|
||||||
{
|
bool str_partition(const str src, const str patt, str *const prefix,
|
||||||
|
str *const suffix) {
|
||||||
const size_t patt_len = str_len(patt);
|
const size_t patt_len = str_len(patt);
|
||||||
|
|
||||||
if(patt_len > 0 && !str_is_empty(src))
|
if (patt_len > 0 && !str_is_empty(src)) {
|
||||||
{
|
|
||||||
const char *s = memmem(str_ptr(src), str_len(src), str_ptr(patt), patt_len);
|
const char *s = memmem(str_ptr(src), str_len(src), str_ptr(patt), patt_len);
|
||||||
|
|
||||||
if(s)
|
if (s) {
|
||||||
{
|
|
||||||
if (prefix)
|
if (prefix)
|
||||||
str_assign(prefix, str_ref_chars(str_ptr(src), s - str_ptr(src)));
|
str_assign(prefix, str_ref_chars(str_ptr(src), s - str_ptr(src)));
|
||||||
|
|
||||||
if(suffix)
|
if (suffix) {
|
||||||
{
|
|
||||||
s += patt_len;
|
s += patt_len;
|
||||||
str_assign(suffix, str_ref_chars(s, str_end(src) - s));
|
str_assign(suffix, str_ref_chars(s, str_end(src) - s));
|
||||||
}
|
}
|
||||||
@@ -673,36 +615,32 @@ bool str_partition(const str src, const str patt, str* const prefix, str* const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// comparison functions
|
// comparison functions
|
||||||
int str_order_asc(const void* const s1, const void* const s2)
|
int str_order_asc(const void *const s1, const void *const s2) {
|
||||||
{
|
|
||||||
return str_cmp(*(const str *)s1, *(const str *)s2);
|
return str_cmp(*(const str *)s1, *(const str *)s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_order_desc(const void* const s1, const void* const s2)
|
int str_order_desc(const void *const s1, const void *const s2) {
|
||||||
{
|
|
||||||
return -str_cmp(*(const str *)s1, *(const str *)s2);
|
return -str_cmp(*(const str *)s1, *(const str *)s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_order_asc_ci(const void* const s1, const void* const s2)
|
int str_order_asc_ci(const void *const s1, const void *const s2) {
|
||||||
{
|
|
||||||
return str_cmp_ci(*(const str *)s1, *(const str *)s2);
|
return str_cmp_ci(*(const str *)s1, *(const str *)s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_order_desc_ci(const void* const s1, const void* const s2)
|
int str_order_desc_ci(const void *const s1, const void *const s2) {
|
||||||
{
|
|
||||||
return -str_cmp_ci(*(const str *)s1, *(const str *)s2);
|
return -str_cmp_ci(*(const str *)s1, *(const str *)s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sorting
|
// sorting
|
||||||
void str_sort_range(const str_cmp_func cmp, str* const array, const size_t count)
|
void str_sort_range(const str_cmp_func cmp, str *const array,
|
||||||
{
|
const size_t count) {
|
||||||
if (array && count > 1)
|
if (array && count > 1)
|
||||||
qsort(array, count, sizeof(array[0]), cmp);
|
qsort(array, count, sizeof(array[0]), cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// searching
|
// searching
|
||||||
const str* str_search_range(const str key, const str* const array, const size_t count)
|
const str *str_search_range(const str key, const str *const array,
|
||||||
{
|
const size_t count) {
|
||||||
if (!array || count == 0)
|
if (!array || count == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -713,8 +651,8 @@ const str* str_search_range(const str key, const str* const array, const size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// partitioning
|
// partitioning
|
||||||
size_t str_partition_range(bool (*pred)(const str), str* const array, const size_t count)
|
size_t str_partition_range(bool (*pred)(const str), str *const array,
|
||||||
{
|
const size_t count) {
|
||||||
if (!array)
|
if (!array)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -732,8 +670,7 @@ size_t str_partition_range(bool (*pred)(const str), str* const array, const size
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unique partitioning
|
// unique partitioning
|
||||||
size_t str_unique_range(str* const array, const size_t count)
|
size_t str_unique_range(str *const array, const size_t count) {
|
||||||
{
|
|
||||||
if (!array || count == 0)
|
if (!array || count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -755,8 +692,7 @@ size_t str_unique_range(str* const array, const size_t count)
|
|||||||
// string iterator function
|
// string iterator function
|
||||||
#ifdef __STDC_UTF_32__
|
#ifdef __STDC_UTF_32__
|
||||||
|
|
||||||
char32_t str_cp_iterator_next(str_cp_iterator* const it)
|
char32_t str_cp_iterator_next(str_cp_iterator *const it) {
|
||||||
{
|
|
||||||
if (it->curr >= it->end)
|
if (it->curr >= it->end)
|
||||||
return CPI_END_OF_STRING;
|
return CPI_END_OF_STRING;
|
||||||
|
|
||||||
@@ -782,20 +718,15 @@ char32_t str_cp_iterator_next(str_cp_iterator* const it)
|
|||||||
#endif // ifdef __STDC_UTF_32__
|
#endif // ifdef __STDC_UTF_32__
|
||||||
|
|
||||||
// tokeniser
|
// tokeniser
|
||||||
static inline
|
static inline bool is_delim(const str_tok_state *const state, const char c) {
|
||||||
bool is_delim(const str_tok_state* const state, const char c)
|
|
||||||
{
|
|
||||||
return state->bits[(unsigned char)c >> 3] & (1 << (c & 0x7));
|
return state->bits[(unsigned char)c >> 3] & (1 << (c & 0x7));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline void set_bit(str_tok_state *const state, const char c) {
|
||||||
void set_bit(str_tok_state* const state, const char c)
|
|
||||||
{
|
|
||||||
state->bits[(unsigned char)c >> 3] |= (1 << (c & 0x7));
|
state->bits[(unsigned char)c >> 3] |= (1 << (c & 0x7));
|
||||||
}
|
}
|
||||||
|
|
||||||
void str_tok_delim(str_tok_state* const state, const str delim_set)
|
void str_tok_delim(str_tok_state *const state, const str delim_set) {
|
||||||
{
|
|
||||||
memset(state->bits, 0, sizeof(state->bits));
|
memset(state->bits, 0, sizeof(state->bits));
|
||||||
|
|
||||||
const char *const end = str_end(delim_set);
|
const char *const end = str_end(delim_set);
|
||||||
@@ -804,24 +735,22 @@ void str_tok_delim(str_tok_state* const state, const str delim_set)
|
|||||||
set_bit(state, *s);
|
set_bit(state, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void str_tok_init(str_tok_state* const state, const str src, const str delim_set)
|
void str_tok_init(str_tok_state *const state, const str src,
|
||||||
{
|
const str delim_set) {
|
||||||
state->src = str_ptr(src);
|
state->src = str_ptr(src);
|
||||||
state->end = str_end(src);
|
state->end = str_end(src);
|
||||||
|
|
||||||
str_tok_delim(state, delim_set);
|
str_tok_delim(state, delim_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool str_tok(str* const dest, str_tok_state* const state)
|
bool str_tok(str *const dest, str_tok_state *const state) {
|
||||||
{
|
|
||||||
// token start
|
// token start
|
||||||
const char *begin = state->src;
|
const char *begin = state->src;
|
||||||
|
|
||||||
while (begin < state->end && is_delim(state, *begin))
|
while (begin < state->end && is_delim(state, *begin))
|
||||||
++begin;
|
++begin;
|
||||||
|
|
||||||
if(begin == state->end)
|
if (begin == state->end) {
|
||||||
{
|
|
||||||
str_clear(dest);
|
str_clear(dest);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
139
src/str.h
139
src/str.h
@@ -32,16 +32,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// string type ----------------------------------------------------------------------------
|
// string type
|
||||||
typedef struct
|
// ----------------------------------------------------------------------------
|
||||||
{
|
typedef struct {
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
size_t info;
|
size_t info;
|
||||||
} str;
|
} str;
|
||||||
@@ -53,38 +53,35 @@ typedef struct
|
|||||||
#define str_ref_info(n) ((n) << 1)
|
#define str_ref_info(n) ((n) << 1)
|
||||||
#define str_owner_info(n) (str_ref_info(n) | 1)
|
#define str_owner_info(n) (str_ref_info(n) | 1)
|
||||||
|
|
||||||
// string properties ----------------------------------------------------------------------
|
// string properties
|
||||||
// length of the string
|
// ---------------------------------------------------------------------- length
|
||||||
static inline
|
// of the string
|
||||||
size_t str_len(const str s) { return s.info >> 1; }
|
static inline size_t str_len(const str s) { return s.info >> 1; }
|
||||||
|
|
||||||
// pointer to the string
|
// pointer to the string
|
||||||
static inline
|
static inline const char *str_ptr(const str s) {
|
||||||
const char* str_ptr(const str s)
|
|
||||||
{
|
|
||||||
extern const char *const str_empty_string;
|
extern const char *const str_empty_string;
|
||||||
|
|
||||||
return s.ptr ? s.ptr : str_empty_string;
|
return s.ptr ? s.ptr : str_empty_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of the string
|
// end of the string
|
||||||
static inline
|
static inline const char *str_end(const str s) {
|
||||||
const char* str_end(const str s) { return str_ptr(s) + str_len(s); }
|
return str_ptr(s) + str_len(s);
|
||||||
|
}
|
||||||
|
|
||||||
// test if the string is empty
|
// test if the string is empty
|
||||||
static inline
|
static inline bool str_is_empty(const str s) { return str_len(s) == 0; }
|
||||||
bool str_is_empty(const str s) { return str_len(s) == 0; }
|
|
||||||
|
|
||||||
// test if the string is allocated on the heap
|
// test if the string is allocated on the heap
|
||||||
static inline
|
static inline bool str_is_owner(const str s) { return (s.info & 1) != 0; }
|
||||||
bool str_is_owner(const str s) { return (s.info & 1) != 0; }
|
|
||||||
|
|
||||||
// test if the string is a reference
|
// test if the string is a reference
|
||||||
static inline
|
static inline bool str_is_ref(const str s) { return !str_is_owner(s); }
|
||||||
bool str_is_ref(const str s) { return !str_is_owner(s); }
|
|
||||||
|
|
||||||
// string memory control -------------------------------------------------------------------
|
// string memory control
|
||||||
// free memory allocated for the string
|
// ------------------------------------------------------------------- free
|
||||||
|
// memory allocated for the string
|
||||||
void str_free(const str s);
|
void str_free(const str s);
|
||||||
|
|
||||||
// automatic cleanup
|
// automatic cleanup
|
||||||
@@ -92,40 +89,51 @@ void str_free_auto(const str* const ps);
|
|||||||
|
|
||||||
#define str_auto str __attribute__((cleanup(str_free_auto)))
|
#define str_auto str __attribute__((cleanup(str_free_auto)))
|
||||||
|
|
||||||
// string movements -----------------------------------------------------------------------
|
// string movements
|
||||||
// free target string, then assign the new value to it
|
// ----------------------------------------------------------------------- free
|
||||||
static inline
|
// target string, then assign the new value to it
|
||||||
void str_assign(str* const ps, const str s) { str_free(*ps); *ps = s; }
|
static inline void str_assign(str *const ps, const str s) {
|
||||||
|
str_free(*ps);
|
||||||
|
*ps = s;
|
||||||
|
}
|
||||||
|
|
||||||
// move the string, resetting the source to str_null
|
// move the string, resetting the source to str_null
|
||||||
static inline
|
static inline str str_move(str *const ps) {
|
||||||
str str_move(str* const ps) { const str t = *ps; *ps = str_null; return t; }
|
const str t = *ps;
|
||||||
|
*ps = str_null;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
// pass ownership of the string
|
// pass ownership of the string
|
||||||
static inline
|
static inline str str_pass(str *const ps) {
|
||||||
str str_pass(str* const ps) { const str t = *ps; ps->info &= ~(size_t)1; return t; }
|
const str t = *ps;
|
||||||
|
ps->info &= ~(size_t)1;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
// swap two string objects
|
// swap two string objects
|
||||||
void str_swap(str *const s1, str *const s2);
|
void str_swap(str *const s1, str *const s2);
|
||||||
|
|
||||||
// string helpers --------------------------------------------------------------------------
|
// string helpers
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
// reset the string to str_null
|
// reset the string to str_null
|
||||||
static inline
|
static inline void str_clear(str *const ps) { str_assign(ps, str_null); }
|
||||||
void str_clear(str* const ps) { str_assign(ps, str_null); }
|
|
||||||
|
|
||||||
// compare two strings lexicographically
|
// compare two strings lexicographically
|
||||||
int str_cmp(const str s1, const str s2);
|
int str_cmp(const str s1, const str s2);
|
||||||
|
|
||||||
// test if two strings match
|
// test if two strings match
|
||||||
static inline
|
static inline bool str_eq(const str s1, const str s2) {
|
||||||
bool str_eq(const str s1, const str s2) { return str_cmp(s1, s2) == 0; }
|
return str_cmp(s1, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// case-insensitive comparison
|
// case-insensitive comparison
|
||||||
int str_cmp_ci(const str s1, const str s2);
|
int str_cmp_ci(const str s1, const str s2);
|
||||||
|
|
||||||
// case-insensitive match
|
// case-insensitive match
|
||||||
static inline
|
static inline bool str_eq_ci(const str s1, const str s2) {
|
||||||
bool str_eq_ci(const str s1, const str s2) { return str_cmp_ci(s1, s2) == 0; }
|
return str_cmp_ci(s1, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// test for prefix
|
// test for prefix
|
||||||
bool str_has_prefix(const str s, const str prefix);
|
bool str_has_prefix(const str s, const str prefix);
|
||||||
@@ -133,7 +141,8 @@ bool str_has_prefix(const str s, const str prefix);
|
|||||||
// test for suffix
|
// test for suffix
|
||||||
bool str_has_suffix(const str s, const str suffix);
|
bool str_has_suffix(const str s, const str suffix);
|
||||||
|
|
||||||
// string composition ------------------------------------------------------------------
|
// string composition
|
||||||
|
// ------------------------------------------------------------------
|
||||||
// implementation helpers
|
// implementation helpers
|
||||||
int str_dup_impl(str *const dest, const str s);
|
int str_dup_impl(str *const dest, const str s);
|
||||||
int str_cpy_to_fd(const int fd, const str s);
|
int str_cpy_to_fd(const int fd, const str s);
|
||||||
@@ -168,9 +177,12 @@ int str_cat_range_to_stream(FILE* const stream, const str* src, size_t count);
|
|||||||
})
|
})
|
||||||
|
|
||||||
// implementation helpers
|
// implementation helpers
|
||||||
int str_join_range_impl(str* const dest, const str sep, const str* src, size_t count);
|
int str_join_range_impl(str *const dest, const str sep, const str *src,
|
||||||
int str_join_range_to_fd(const int fd, const str sep, const str* src, size_t count);
|
size_t count);
|
||||||
int str_join_range_to_stream(FILE* const stream, const str sep, const str* src, size_t count);
|
int str_join_range_to_fd(const int fd, const str sep, const str *src,
|
||||||
|
size_t count);
|
||||||
|
int str_join_range_to_stream(FILE *const stream, const str sep, const str *src,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
// join strings around the separator
|
// join strings around the separator
|
||||||
#define str_join_range(dest, sep, src, count) \
|
#define str_join_range(dest, sep, src, count) \
|
||||||
@@ -187,12 +199,14 @@ int str_join_range_to_stream(FILE* const stream, const str sep, const str* src,
|
|||||||
str_join_range((dest), (sep), args, sizeof(args) / sizeof(args[0])); \
|
str_join_range((dest), (sep), args, sizeof(args) / sizeof(args[0])); \
|
||||||
})
|
})
|
||||||
|
|
||||||
// constructors ----------------------------------------------------------------------------
|
// constructors
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
// string reference from a string literal
|
// string reference from a string literal
|
||||||
#define str_lit(s) ((str){"" s, str_ref_info(sizeof(s) - 1)})
|
#define str_lit(s) ((str){"" s, str_ref_info(sizeof(s) - 1)})
|
||||||
|
|
||||||
static inline
|
static inline str str_ref_impl(const str s) {
|
||||||
str str_ref_impl(const str s) { return (str){ s.ptr, s.info & ~(size_t)1 }; }
|
return (str){s.ptr, s.info & ~(size_t)1};
|
||||||
|
}
|
||||||
|
|
||||||
str str_ref_from_ptr(const char *const s);
|
str str_ref_from_ptr(const char *const s);
|
||||||
|
|
||||||
@@ -219,9 +233,11 @@ int str_from_file(str* const dest, const char* const file_name);
|
|||||||
// read maximum nread bytes from file, write bytes read. 0 reads until EOS.
|
// read maximum nread bytes from file, write bytes read. 0 reads until EOS.
|
||||||
int str_from_stream(str *const dest, const char *const file_name, int *nread);
|
int str_from_stream(str *const dest, const char *const file_name, int *nread);
|
||||||
|
|
||||||
// searching and sorting --------------------------------------------------------------------
|
// searching and sorting
|
||||||
// string partitioning (substring search)
|
// -------------------------------------------------------------------- string
|
||||||
bool str_partition(const str src, const str patt, str* const prefix, str* const suffix);
|
// partitioning (substring search)
|
||||||
|
bool str_partition(const str src, const str patt, str *const prefix,
|
||||||
|
str *const suffix);
|
||||||
|
|
||||||
// comparison functions
|
// comparison functions
|
||||||
typedef int (*str_cmp_func)(const void *, const void *);
|
typedef int (*str_cmp_func)(const void *, const void *);
|
||||||
@@ -232,18 +248,22 @@ int str_order_asc_ci(const void* const s1, const void* const s2);
|
|||||||
int str_order_desc_ci(const void *const s1, const void *const s2);
|
int str_order_desc_ci(const void *const s1, const void *const s2);
|
||||||
|
|
||||||
// sort array of strings
|
// sort array of strings
|
||||||
void str_sort_range(const str_cmp_func cmp, str* const array, const size_t count);
|
void str_sort_range(const str_cmp_func cmp, str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// searching
|
// searching
|
||||||
const str* str_search_range(const str key, const str* const array, const size_t count);
|
const str *str_search_range(const str key, const str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// partitioning
|
// partitioning
|
||||||
size_t str_partition_range(bool (*pred)(const str), str* const array, const size_t count);
|
size_t str_partition_range(bool (*pred)(const str), str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// unique partitioning
|
// unique partitioning
|
||||||
size_t str_unique_range(str *const array, const size_t count);
|
size_t str_unique_range(str *const array, const size_t count);
|
||||||
|
|
||||||
// UTF-32 codepoint iterator ----------------------------------------------------------------
|
// UTF-32 codepoint iterator
|
||||||
|
// ----------------------------------------------------------------
|
||||||
#ifdef __STDC_UTF_32__
|
#ifdef __STDC_UTF_32__
|
||||||
#include <uchar.h>
|
#include <uchar.h>
|
||||||
|
|
||||||
@@ -258,21 +278,19 @@ size_t str_unique_range(str* const array, const size_t count);
|
|||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
#define for_each_cp(var, src, it) \
|
#define for_each_cp(var, src, it) \
|
||||||
for(str_cp_iterator it = str_make_cp_iterator(src); (var = str_cp_iterator_next(&it)) <= 0x10FFFFu;)
|
for (str_cp_iterator it = str_make_cp_iterator(src); \
|
||||||
|
(var = str_cp_iterator_next(&it)) <= 0x10FFFFu;)
|
||||||
|
|
||||||
#define CAT1(x, y) CAT2(x, y)
|
#define CAT1(x, y) CAT2(x, y)
|
||||||
#define CAT2(x, y) x##y
|
#define CAT2(x, y) x##y
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
const char *curr;
|
const char *curr;
|
||||||
const char *const end;
|
const char *const end;
|
||||||
mbstate_t state;
|
mbstate_t state;
|
||||||
} str_cp_iterator;
|
} str_cp_iterator;
|
||||||
|
|
||||||
static inline
|
static inline str_cp_iterator str_make_cp_iterator(const str s) {
|
||||||
str_cp_iterator str_make_cp_iterator(const str s)
|
|
||||||
{
|
|
||||||
return (str_cp_iterator){.curr = str_ptr(s), .end = str_end(s)};
|
return (str_cp_iterator){.curr = str_ptr(s), .end = str_end(s)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,14 +298,15 @@ char32_t str_cp_iterator_next(str_cp_iterator* const it);
|
|||||||
|
|
||||||
#endif // ifdef __STDC_UTF_32__
|
#endif // ifdef __STDC_UTF_32__
|
||||||
|
|
||||||
// tokeniser --------------------------------------------------------------------------------
|
// tokeniser
|
||||||
typedef struct
|
// --------------------------------------------------------------------------------
|
||||||
{
|
typedef struct {
|
||||||
unsigned char bits[32]; // 256 / 8
|
unsigned char bits[32]; // 256 / 8
|
||||||
const char *src, *end;
|
const char *src, *end;
|
||||||
} str_tok_state;
|
} str_tok_state;
|
||||||
|
|
||||||
void str_tok_init(str_tok_state* const state, const str src, const str delim_set);
|
void str_tok_init(str_tok_state *const state, const str src,
|
||||||
|
const str delim_set);
|
||||||
bool str_tok(str *const dest, str_tok_state *const state);
|
bool str_tok(str *const dest, str_tok_state *const state);
|
||||||
void str_tok_delim(str_tok_state *const state, const str delim_set);
|
void str_tok_delim(str_tok_state *const state, const str delim_set);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct sc_array_str names;
|
struct sc_array_str names;
|
||||||
struct sc_array_ptr addresses;
|
struct sc_array_ptr addresses;
|
||||||
@@ -16,7 +15,6 @@ typedef struct {
|
|||||||
|
|
||||||
sc_array_def(SymbolInfos, syms);
|
sc_array_def(SymbolInfos, syms);
|
||||||
|
|
||||||
|
|
||||||
struct dl_phdr_info;
|
struct dl_phdr_info;
|
||||||
struct sc_array_memreg;
|
struct sc_array_memreg;
|
||||||
HiloadResult hi_create_symbol_info(SymbolInfos *,
|
HiloadResult hi_create_symbol_info(SymbolInfos *,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef TYPES_H_
|
#ifndef TYPES_H_
|
||||||
#define TYPES_H_
|
#define TYPES_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ static int otherValue = 0;
|
|||||||
int getNewValue(int x);
|
int getNewValue(int x);
|
||||||
|
|
||||||
#pragma GCC visibility pop
|
#pragma GCC visibility pop
|
||||||
}
|
} // namespace minimal_lib
|
||||||
#endif // MINIMAL_LIB_H_
|
#endif // MINIMAL_LIB_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user