Skip to content

Commit 28c855b

Browse files
committed
contrib: sync csnippets
Signed-off-by: He Xian <hexian000@outlook.com>
1 parent affa51e commit 28c855b

6 files changed

Lines changed: 246 additions & 69 deletions

File tree

contrib/csnippets/net/url.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
* This code is licensed under MIT license (see LICENSE for details) */
33

44
#include "url.h"
5+
#include "utils/ascii.h"
56

6-
#include <ctype.h>
77
#include <stdbool.h>
88
#include <stddef.h>
99
#include <stdint.h>
@@ -102,33 +102,39 @@ escape(char *buf, size_t buf_size, const char *str, const size_t len,
102102
return cap - buf_size;
103103
}
104104

105-
static size_t escape_host(
105+
#define S_UNRESERVED "-_.~"
106+
#define S_SUB_DELIMS "!$&'()*+,;="
107+
#define S_PCHAR S_UNRESERVED S_SUB_DELIMS ":@"
108+
109+
static size_t escape_hostport(
106110
char *buf, const size_t buf_size, const char *host, const size_t len)
107111
{
108112
/* RFC 1738, RFC 2732 */
109113
return escape(
110-
buf, buf_size, host, len, "-_.~!$&'()*+,;=:[]<>\"", false);
114+
buf, buf_size, host, len, S_UNRESERVED S_SUB_DELIMS ":[]",
115+
false);
111116
}
112117

113118
static size_t escape_userinfo(
114119
char *buf, const size_t buf_size, const char *userinfo,
115120
const size_t len)
116121
{
117-
return escape(buf, buf_size, userinfo, len, "-_.~$&+,;=", false);
122+
return escape(
123+
buf, buf_size, userinfo, len, S_UNRESERVED S_SUB_DELIMS ":",
124+
false);
118125
}
119126

120127
static size_t escape_query(
121128
char *buf, const size_t buf_size, const char *query, const size_t len)
122129
{
123-
return escape(buf, buf_size, query, len, "-_.~", true);
130+
return escape(buf, buf_size, query, len, S_PCHAR "/?", true);
124131
}
125132

126133
static size_t escape_fragment(
127134
char *buf, const size_t buf_size, const char *fragment,
128135
const size_t len)
129136
{
130-
return escape(
131-
buf, buf_size, fragment, len, "-_.~$&+,/:;=?@!()*", false);
137+
return escape(buf, buf_size, fragment, len, S_PCHAR "/?", false);
132138
}
133139

134140
size_t
@@ -208,7 +214,7 @@ size_t url_build(char *buf, size_t buf_size, const struct url *url)
208214
APPEND(url->userinfo);
209215
APPENDCH('@');
210216
}
211-
APPENDN(escape_host(
217+
APPENDN(escape_hostport(
212218
buf, buf_size, url->host, strlen(url->host)));
213219
}
214220
if (url->path != NULL) {
@@ -274,14 +280,6 @@ static bool unescape(char *str, const bool space)
274280
return true;
275281
}
276282

277-
static inline char *strlower(char *restrict s)
278-
{
279-
for (unsigned char *p = (unsigned char *)s; *p != '\0'; ++p) {
280-
*p = tolower(*p);
281-
}
282-
return s;
283-
}
284-
285283
bool url_parse(char *raw, struct url *restrict url)
286284
{
287285
/* safety check */

contrib/csnippets/utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ target_sources(csnippets
66
"${CMAKE_CURRENT_SOURCE_DIR}/slog.c"
77
PUBLIC
88
"${CMAKE_CURRENT_SOURCE_DIR}/arraysize.h"
9+
"${CMAKE_CURRENT_SOURCE_DIR}/ascii.h"
910
"${CMAKE_CURRENT_SOURCE_DIR}/buffer.h"
1011
"${CMAKE_CURRENT_SOURCE_DIR}/debug.h"
1112
"${CMAKE_CURRENT_SOURCE_DIR}/formats.h"

contrib/csnippets/utils/ascii.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* csnippets (c) 2019-2025 He Xian <hexian000@outlook.com>
2+
* This code is licensed under MIT license (see LICENSE for details) */
3+
4+
#ifndef UTILS_ASCII_H
5+
#define UTILS_ASCII_H
6+
7+
#define isascii(c) (((c) & ~0x7f) == 0)
8+
9+
#define isdigit(c) ('0' <= (c) && (c) <= '9')
10+
#define isalpha(c) (('A' <= (c) && (c) <= 'Z') || ('a' <= (c) && (c) <= 'z'))
11+
#define isalnum(c) (isdigit(c) || isalpha(c))
12+
#define isspace(c) \
13+
((c) == '\t' || (c) == '\n' || (c) == '\v' || (c) == '\f' || \
14+
(c) == '\r' || (c) == ' ')
15+
#define iscntrl(c) (isascii(c) && ((c) <= '\x1f' || (c) == '\x7f'))
16+
#define islower(c) ('a' <= (c) && (c) <= 'z')
17+
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
18+
#define isprint(c) ('\x20' <= (c) && (c) <= '\x7e')
19+
#define isgraph(c) ('\x21' <= (c) && (c) <= '\x7e')
20+
#define ispunct(c) (isgraph(c) && !isalnum(c))
21+
#define isxdigit(c) \
22+
(isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))
23+
#define isblank(c) ((c) == ' ' || (c) == '\t')
24+
25+
#define tolower(c) ('A' <= (c) && (c) <= 'Z' ? (c) - 'A' + 'a' : (c))
26+
#define toupper(c) ('a' <= (c) && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
27+
28+
static inline char *strlower(char *restrict s)
29+
{
30+
for (unsigned char *p = (unsigned char *)s; *p; p++) {
31+
*p = tolower(*p);
32+
}
33+
return s;
34+
}
35+
36+
static inline char *strupper(char *restrict s)
37+
{
38+
for (unsigned char *p = (unsigned char *)s; *p; p++) {
39+
*p = toupper(*p);
40+
}
41+
return s;
42+
}
43+
44+
static inline char *strtrimleftspace(char *restrict s)
45+
{
46+
const unsigned char *p = (unsigned char *)s;
47+
while (*p && isspace(*p)) {
48+
p++;
49+
}
50+
return (char *)p;
51+
}
52+
53+
static inline char *strtrimrightspace(char *restrict s)
54+
{
55+
unsigned char *e;
56+
for (e = (unsigned char *)s; *e; e++) {
57+
}
58+
e--;
59+
while ((unsigned char *)s < e && isspace(*e)) {
60+
*e-- = '\0';
61+
}
62+
return s;
63+
}
64+
65+
static inline char *strtrimspace(char *restrict s)
66+
{
67+
return strtrimrightspace(strtrimleftspace(s));
68+
}
69+
70+
#endif /* UTILS_ASCII_H */

contrib/csnippets/utils/buffer.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010
#include <stdlib.h>
1111
#include <string.h>
1212

13+
/**
14+
* Append formatted text into a fixed buffer using a va_list.
15+
*
16+
* Behavior:
17+
* - Writes at most the remaining capacity.
18+
* - Ensures there is a trailing NUL in the buffer storage.
19+
* - Advances len by up to (cap - len - 1).
20+
*
21+
* Returns the number of characters that would have been written (excluding
22+
* the terminating NUL), as per vsnprintf semantics. Non-positive values
23+
* indicate an encoding/formatting error or zero available space.
24+
*/
1325
int buf_vappendf(
1426
struct buffer *restrict buf, const char *restrict format, va_list args)
1527
{
@@ -34,6 +46,17 @@ int buf_appendf(struct buffer *restrict buf, const char *restrict format, ...)
3446
return ret;
3547
}
3648

49+
/**
50+
* Ensure a growable buffer has capacity of at least `want` bytes.
51+
*
52+
* Growth strategy:
53+
* - Below 256 bytes: jump to 256.
54+
* - Below 4096 bytes: double the current capacity.
55+
* - 4096 and above: grow by cap/4 + 3*4096/4 to moderate fragmentation.
56+
*
57+
* Always reserves one extra byte for NUL-termination. On allocation failure,
58+
* returns the original pointer unchanged.
59+
*/
3760
struct vbuffer *vbuf_grow(struct vbuffer *vbuf, const size_t want)
3861
{
3962
const size_t maxcap = SIZE_MAX - sizeof(struct vbuffer) - 1;
@@ -80,6 +103,12 @@ struct vbuffer *vbuf_grow(struct vbuffer *vbuf, const size_t want)
80103
return newbuf;
81104
}
82105

106+
/**
107+
* Append up to n bytes to a growable buffer.
108+
* - Attempts to grow to fit; if growth fails, appends what fits.
109+
* - Maintains a trailing NUL in the reserved byte (does not change len).
110+
* - If len == cap (previous alloc failure), the append is skipped.
111+
*/
83112
struct vbuffer *
84113
vbuf_append(struct vbuffer *restrict vbuf, const void *restrict data, size_t n)
85114
{
@@ -105,6 +134,11 @@ vbuf_append(struct vbuffer *restrict vbuf, const void *restrict data, size_t n)
105134
return vbuf;
106135
}
107136

137+
/**
138+
* Append formatted text to a growable buffer using a va_list.
139+
* Performs a two-pass attempt: try in-place then grow and retry.
140+
* Keeps a trailing NUL in the reserved byte. On failure, truncates to fit.
141+
*/
108142
struct vbuffer *vbuf_vappendf(
109143
struct vbuffer *restrict vbuf, const char *restrict format,
110144
va_list args)

0 commit comments

Comments
 (0)