From bfc1508d26c89c9a36d2d9a827fe2c4ed128884d Mon Sep 17 00:00:00 2001 From: kx Date: Fri, 24 Mar 2023 03:55:33 +0300 Subject: Version 0.1.4 --- csvncgi/strbuf.h | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 csvncgi/strbuf.h (limited to 'csvncgi/strbuf.h') diff --git a/csvncgi/strbuf.h b/csvncgi/strbuf.h new file mode 100644 index 0000000..2d170a0 --- /dev/null +++ b/csvncgi/strbuf.h @@ -0,0 +1,202 @@ + +#ifndef __STRBUF_H +#define __STRBUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRBUF_MAXLINE (2*PATH_MAX) + +typedef void (*strbuf_error)( const char *fmt, ... ); + +struct strbuf +{ + size_t alloc; + size_t len; + strbuf_error fatal; + char *buf; +}; + +/************************************************************************ + Таблица размещается на стороне клиента, а указатель присваивается + переменной strbuf_envtab, который используется функциями чтения файлов + для подстановки значений вместо переменных: + + ${root-title}, ${root-desc}, ${repo}, ${repo-desc}, ... + + Освобождать выделенную память нет необходимости, так как таблица + используется в CGI-скрипте, который срабатывает однократно. + + При необходимости повторного создания таблицы переменных, + надо освободить память с помощью envtab_release( &strbuf_envtab ) + которая обнулит указатель strbuf_envtab, являющийся адресом первой + записи в таблице. + */ +typedef void (*envtab_error)( const char *fmt, ... ); + +struct symbol +{ + char *name; + char *value; + + struct symbol *next; +}; + +extern struct symbol *strbuf_envtab; + +extern struct symbol *envtab_install( struct symbol **sym, const char *n, const char *v, envtab_error fatal ); +extern struct symbol *envtab_lookup( struct symbol **sym, const char *n ); +extern void envtab_release( struct symbol **sym ); +/* + ************************************************************************/ + + +extern char strbuf_slopbuf[]; +extern void strbuf_fatal( const char *fmt, ... ); + +#define STRBUF_INIT { .alloc = 0, .len = 0, .fatal = strbuf_fatal, .buf = strbuf_slopbuf } + +extern void strbuf_grow( struct strbuf *sb, size_t amount ); +extern void strbuf_init( struct strbuf *sb, strbuf_error fatal, size_t alloc ); +extern void strbuf_release( struct strbuf *sb ); +extern char *strbuf_detach( struct strbuf *sb, size_t *sz ); +extern void strbuf_attach( struct strbuf *sb, void *str, size_t len, size_t mem ); + +static inline size_t strbuf_avail( const struct strbuf *sb ) +{ + return sb->alloc ? sb->alloc - sb->len - 1 : 0; +} + +static inline void strbuf_setlen(struct strbuf *sb, size_t len) +{ + if( len > (sb->alloc ? sb->alloc - 1 : 0) ) + sb->fatal( "BUG: strbuf_setlen() beyond buffer" ); + sb->len = len; + if (sb->buf != strbuf_slopbuf) + sb->buf[len] = '\0'; + else + if( !strbuf_slopbuf[0] ) sb->fatal( "BUG: strbuf_slopbuf[0] = '\0'" ); +} + +#define strbuf_reset(sb) strbuf_setlen(sb, 0) + + +/*************************************************************************** + BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + @cond: the compile-time condition which must be true. + + Your compile will fail if the condition isn't true, or can't be evaluated + by the compiler. This can be used in an expression: its value is "0". + + Example: + #define foo_to_char(foo) \ + ((char *)(foo) \ + + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + ***************************************************************************/ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define SWAP(a, b) \ + do { \ + void *_swap_a_ptr = &(a); \ + void *_swap_b_ptr = &(b); \ + unsigned char _swap_buffer[sizeof(a)]; \ + memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \ + memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a) + \ + BUILD_ASSERT_OR_ZERO(sizeof(a) == sizeof(b))); \ + memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \ + } while (0) + +static inline void strbuf_swap( struct strbuf *a, struct strbuf *b ) +{ + SWAP(*a, *b); +} + + +extern void strbuf_ltrim( struct strbuf *sb ); +extern void strbuf_rtrim( struct strbuf *sb ); +extern void strbuf_trim( struct strbuf *sb ); + +#ifndef is_dir_sep +static inline int is_dir_sep( int c ) +{ + return c == '/'; +} +#endif +static inline int is_absolute_path( const char *path ) +{ + return is_dir_sep( path[0] ); +} + +extern void strbuf_trim_trailing_dir_sep( struct strbuf *sb ); +extern void strbuf_trim_trailing_newline( struct strbuf *sb ); + +extern int strbuf_cmp( const struct strbuf *a, const struct strbuf *b ); + + +/* Adding data to the buffer */ + +extern void strbuf_add( struct strbuf *sb, const void *data, size_t len ); +extern void strbuf_addbuf( struct strbuf *sb, const struct strbuf *sb2 ); +extern void strbuf_addbuf_percentquote( struct strbuf *dst, const struct strbuf *src ); + + +/* Add a single ASCII character to the buffer. */ +static inline void strbuf_addch( struct strbuf *sb, int c ) +{ + if( !strbuf_avail(sb) ) + strbuf_grow(sb, 1); + sb->buf[sb->len++] = c; + sb->buf[sb->len] = '\0'; +} + +/* Add n ASCII characters to the buffer. */ +extern void strbuf_addchars( struct strbuf *sb, int c, size_t n ); + +/* Add a NUL-terminated string to the buffer. */ +static inline void strbuf_addstr( struct strbuf *sb, const char *s ) +{ + strbuf_add( sb, (const void *)s, strlen(s) ); +} + +extern void strbuf_vaddf( struct strbuf *sb, const char *fmt, va_list ap ); +extern void strbuf_addf( struct strbuf *sb, const char *fmt, ... ); + +extern size_t strbuf_fread( struct strbuf *sb, FILE *fp ); +extern size_t strbuf_env_fread( struct strbuf *sb, FILE *fp ); +extern size_t strbuf_fwrite( struct strbuf *sb, FILE *fp ); + +extern ssize_t strbuf_read( struct strbuf *sb, int fd, size_t hint ); +extern ssize_t strbuf_write( struct strbuf *sb, int fd ); + + +/* XML/HTML quoted: */ +extern void strbuf_addstr_xml_quoted( struct strbuf *sb, const char *s ); +extern void strbuf_addstr_html_quoted( struct strbuf *sb, const char *s ); + +/* urlencode: */ +typedef int (*char_predicate)(char ch); + +extern int is_rfc3986_unreserved( char ch ); +extern int is_rfc3986_reserved_or_unreserved( char ch ); + +extern void strbuf_addstr_urlencode( struct strbuf *sb, const char *name, char_predicate allow_unencoded_fn ); + + +extern void strbuf_humanise_bytes( struct strbuf *sb, off_t bytes ); +extern void strbuf_humanise_rate( struct strbuf *sb, off_t bytes ); + + +extern int is_directory( const char *path ); + +extern void strbuf_selfdir( struct strbuf *sb ); +extern void strbuf_relpath( struct strbuf *sb, const char *path ); +extern void strbuf_abspath( struct strbuf *sb, const char *path ); + + +#ifdef __cplusplus +} +#endif + +#endif /* __STRBUF_H */ -- cgit v1.2.3