mirror of
https://github.com/depp/syncfiles.git
synced 2024-11-28 12:51:05 +00:00
Add simple string buffer library
This commit is contained in:
parent
ec3c80360f
commit
0ba00114d6
@ -5,6 +5,7 @@ cc_library(
|
|||||||
name = "lib",
|
name = "lib",
|
||||||
srcs = [
|
srcs = [
|
||||||
"crc32.c",
|
"crc32.c",
|
||||||
|
"strbuf.c",
|
||||||
"toolbox.c",
|
"toolbox.c",
|
||||||
"util.c",
|
"util.c",
|
||||||
],
|
],
|
||||||
@ -13,6 +14,7 @@ cc_library(
|
|||||||
"defs.h",
|
"defs.h",
|
||||||
"endian.h",
|
"endian.h",
|
||||||
"error.h",
|
"error.h",
|
||||||
|
"strbuf.h",
|
||||||
"util.h",
|
"util.h",
|
||||||
],
|
],
|
||||||
copts = COPTS,
|
copts = COPTS,
|
||||||
@ -59,3 +61,15 @@ cc_test(
|
|||||||
":lib",
|
":lib",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "strbuf_test",
|
||||||
|
size = "small",
|
||||||
|
srcs = [
|
||||||
|
"strbuf_test.c",
|
||||||
|
],
|
||||||
|
copts = COPTS,
|
||||||
|
deps = [
|
||||||
|
":lib",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
41
lib/strbuf.c
Normal file
41
lib/strbuf.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2022 Dietrich Epp.
|
||||||
|
// This file is part of SyncFiles. SyncFiles is licensed under the terms of the
|
||||||
|
// Mozilla Public License, version 2.0. See LICENSE.txt for details.
|
||||||
|
#include "lib/strbuf.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
bool StrbufAlloc(struct Strbuf *restrict b, size_t n)
|
||||||
|
{
|
||||||
|
size_t req = n + 1;
|
||||||
|
if (req > b->alloc) {
|
||||||
|
size_t nalloc = (b->alloc + 16) * 3 / 2;
|
||||||
|
if (req > nalloc) {
|
||||||
|
nalloc = req;
|
||||||
|
}
|
||||||
|
char *nbuf = realloc(b->buf, nalloc);
|
||||||
|
if (nbuf == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
b->buf = nbuf;
|
||||||
|
b->alloc = nalloc;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StrbufReserve(struct Strbuf *restrict b, size_t n)
|
||||||
|
{
|
||||||
|
return StrbufAlloc(b, b->len + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StrbufAppendMem(struct Strbuf *restrict b, const char *s, size_t n)
|
||||||
|
{
|
||||||
|
if (!StrbufReserve(b, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(b->buf + b->len, s, n);
|
||||||
|
b->buf[b->len + n] = '\0';
|
||||||
|
b->len += n;
|
||||||
|
return true;
|
||||||
|
}
|
29
lib/strbuf.h
Normal file
29
lib/strbuf.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2022 Dietrich Epp.
|
||||||
|
// This file is part of SyncFiles. SyncFiles is licensed under the terms of the
|
||||||
|
// Mozilla Public License, version 2.0. See LICENSE.txt for details.
|
||||||
|
#ifndef LIB_STRBUF_H
|
||||||
|
#define LIB_STRBUF_H
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "lib/defs.h"
|
||||||
|
|
||||||
|
// A strbuf is a buffer for building a string. The structure can be
|
||||||
|
// zero-initialized.
|
||||||
|
struct Strbuf {
|
||||||
|
char *buf; // String data. May be NULL if strbuf is empty.
|
||||||
|
size_t len; // String length, not including nul terminator.
|
||||||
|
size_t alloc; // Data reserved for string, not including terminator.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reserve enough space in the strbuf to store a string which is n bytes long.
|
||||||
|
// Also reserve enough space for the nul byte after. Return true on success.
|
||||||
|
bool StrbufAlloc(struct Strbuf *restrict b, size_t n);
|
||||||
|
|
||||||
|
// Reserve enough space in the strbuf to append n bytes to the buffer. Also
|
||||||
|
// reserve enough space for the nul byte after. Return true on success.
|
||||||
|
bool StrbufReserve(struct Strbuf *restrict b, size_t n);
|
||||||
|
|
||||||
|
// Append the given data to the buffer. Return true on success.
|
||||||
|
bool StrbufAppendMem(struct Strbuf *restrict b, const char *s, size_t n);
|
||||||
|
|
||||||
|
#endif
|
45
lib/strbuf_test.c
Normal file
45
lib/strbuf_test.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2022 Dietrich Epp.
|
||||||
|
// This file is part of SyncFiles. SyncFiles is licensed under the terms of the
|
||||||
|
// Mozilla Public License, version 2.0. See LICENSE.txt for details.
|
||||||
|
#include "lib/strbuf.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct Segment {
|
||||||
|
const char *buf;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define S "0123456789"
|
||||||
|
#define S8 S S S S S S S S
|
||||||
|
|
||||||
|
static const struct Segment kSegments[] = {
|
||||||
|
{"abc", 3},
|
||||||
|
{S8, 80},
|
||||||
|
{"def", 3},
|
||||||
|
{0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char kOut[] = "abc" S8 "def";
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
struct Strbuf s = {0, 0, 0};
|
||||||
|
for (int i = 0; kSegments[i].buf != NULL; i++) {
|
||||||
|
bool r = StrbufAppendMem(&s, kSegments[i].buf, kSegments[i].size);
|
||||||
|
if (!r) {
|
||||||
|
fputs("StrbufAppendMem returned false\n", stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s.len != sizeof(kOut) - 1 || memcmp(s.buf, kOut, sizeof(kOut)) != 0) {
|
||||||
|
fputs("Invalid result\n", stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(s.buf);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user