mirror of
https://github.com/depp/syncfiles.git
synced 2024-11-24 17:31:40 +00:00
Add simple string buffer library
This commit is contained in:
parent
ec3c80360f
commit
0ba00114d6
@ -5,6 +5,7 @@ cc_library(
|
||||
name = "lib",
|
||||
srcs = [
|
||||
"crc32.c",
|
||||
"strbuf.c",
|
||||
"toolbox.c",
|
||||
"util.c",
|
||||
],
|
||||
@ -13,6 +14,7 @@ cc_library(
|
||||
"defs.h",
|
||||
"endian.h",
|
||||
"error.h",
|
||||
"strbuf.h",
|
||||
"util.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
@ -59,3 +61,15 @@ cc_test(
|
||||
":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