05d292b2 (kx 2023-03-24 03:51:10 +0300 1)
05d292b2 (kx 2023-03-24 03:51:10 +0300 2) #ifndef __STRBUF_H
05d292b2 (kx 2023-03-24 03:51:10 +0300 3) #define __STRBUF_H
05d292b2 (kx 2023-03-24 03:51:10 +0300 4)
05d292b2 (kx 2023-03-24 03:51:10 +0300 5) #ifdef __cplusplus
05d292b2 (kx 2023-03-24 03:51:10 +0300 6) extern "C" {
05d292b2 (kx 2023-03-24 03:51:10 +0300 7) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300 8)
05d292b2 (kx 2023-03-24 03:51:10 +0300 9) #define STRBUF_MAXLINE (2*PATH_MAX)
05d292b2 (kx 2023-03-24 03:51:10 +0300 10)
05d292b2 (kx 2023-03-24 03:51:10 +0300 11) typedef void (*strbuf_error)( const char *fmt, ... );
05d292b2 (kx 2023-03-24 03:51:10 +0300 12)
05d292b2 (kx 2023-03-24 03:51:10 +0300 13) struct strbuf
05d292b2 (kx 2023-03-24 03:51:10 +0300 14) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 15) size_t alloc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 16) size_t len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 17) strbuf_error fatal;
05d292b2 (kx 2023-03-24 03:51:10 +0300 18) char *buf;
05d292b2 (kx 2023-03-24 03:51:10 +0300 19) };
05d292b2 (kx 2023-03-24 03:51:10 +0300 20)
05d292b2 (kx 2023-03-24 03:51:10 +0300 21) /************************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 22) Таблица размещается на стороне клиента, а указатель присваивается
05d292b2 (kx 2023-03-24 03:51:10 +0300 23) переменной strbuf_envtab, который используется функциями чтения файлов
05d292b2 (kx 2023-03-24 03:51:10 +0300 24) для подстановки значений вместо переменных:
05d292b2 (kx 2023-03-24 03:51:10 +0300 25)
05d292b2 (kx 2023-03-24 03:51:10 +0300 26) ${root-title}, ${root-desc}, ${repo}, ${repo-desc}, ...
05d292b2 (kx 2023-03-24 03:51:10 +0300 27)
05d292b2 (kx 2023-03-24 03:51:10 +0300 28) Освобождать выделенную память нет необходимости, так как таблица
05d292b2 (kx 2023-03-24 03:51:10 +0300 29) используется в CGI-скрипте, который срабатывает однократно.
05d292b2 (kx 2023-03-24 03:51:10 +0300 30)
05d292b2 (kx 2023-03-24 03:51:10 +0300 31) При необходимости повторного создания таблицы переменных,
05d292b2 (kx 2023-03-24 03:51:10 +0300 32) надо освободить память с помощью envtab_release( &strbuf_envtab )
05d292b2 (kx 2023-03-24 03:51:10 +0300 33) которая обнулит указатель strbuf_envtab, являющийся адресом первой
05d292b2 (kx 2023-03-24 03:51:10 +0300 34) записи в таблице.
05d292b2 (kx 2023-03-24 03:51:10 +0300 35) */
05d292b2 (kx 2023-03-24 03:51:10 +0300 36) typedef void (*envtab_error)( const char *fmt, ... );
05d292b2 (kx 2023-03-24 03:51:10 +0300 37)
05d292b2 (kx 2023-03-24 03:51:10 +0300 38) struct symbol
05d292b2 (kx 2023-03-24 03:51:10 +0300 39) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 40) char *name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 41) char *value;
05d292b2 (kx 2023-03-24 03:51:10 +0300 42)
05d292b2 (kx 2023-03-24 03:51:10 +0300 43) struct symbol *next;
05d292b2 (kx 2023-03-24 03:51:10 +0300 44) };
05d292b2 (kx 2023-03-24 03:51:10 +0300 45)
05d292b2 (kx 2023-03-24 03:51:10 +0300 46) extern struct symbol *strbuf_envtab;
05d292b2 (kx 2023-03-24 03:51:10 +0300 47)
05d292b2 (kx 2023-03-24 03:51:10 +0300 48) extern struct symbol *envtab_install( struct symbol **sym, const char *n, const char *v, envtab_error fatal );
05d292b2 (kx 2023-03-24 03:51:10 +0300 49) extern struct symbol *envtab_lookup( struct symbol **sym, const char *n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 50) extern void envtab_release( struct symbol **sym );
05d292b2 (kx 2023-03-24 03:51:10 +0300 51) /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 52) ************************************************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 53)
05d292b2 (kx 2023-03-24 03:51:10 +0300 54)
05d292b2 (kx 2023-03-24 03:51:10 +0300 55) extern char strbuf_slopbuf[];
05d292b2 (kx 2023-03-24 03:51:10 +0300 56) extern void strbuf_fatal( const char *fmt, ... );
05d292b2 (kx 2023-03-24 03:51:10 +0300 57)
05d292b2 (kx 2023-03-24 03:51:10 +0300 58) #define STRBUF_INIT { .alloc = 0, .len = 0, .fatal = strbuf_fatal, .buf = strbuf_slopbuf }
05d292b2 (kx 2023-03-24 03:51:10 +0300 59)
05d292b2 (kx 2023-03-24 03:51:10 +0300 60) extern void strbuf_grow( struct strbuf *sb, size_t amount );
05d292b2 (kx 2023-03-24 03:51:10 +0300 61) extern void strbuf_init( struct strbuf *sb, strbuf_error fatal, size_t alloc );
05d292b2 (kx 2023-03-24 03:51:10 +0300 62) extern void strbuf_release( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 63) extern char *strbuf_detach( struct strbuf *sb, size_t *sz );
05d292b2 (kx 2023-03-24 03:51:10 +0300 64) extern void strbuf_attach( struct strbuf *sb, void *str, size_t len, size_t mem );
05d292b2 (kx 2023-03-24 03:51:10 +0300 65)
05d292b2 (kx 2023-03-24 03:51:10 +0300 66) static inline size_t strbuf_avail( const struct strbuf *sb )
05d292b2 (kx 2023-03-24 03:51:10 +0300 67) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 68) return sb->alloc ? sb->alloc - sb->len - 1 : 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 69) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 70)
05d292b2 (kx 2023-03-24 03:51:10 +0300 71) static inline void strbuf_setlen(struct strbuf *sb, size_t len)
05d292b2 (kx 2023-03-24 03:51:10 +0300 72) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 73) if( len > (sb->alloc ? sb->alloc - 1 : 0) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 74) sb->fatal( "BUG: strbuf_setlen() beyond buffer" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 75) sb->len = len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 76) if (sb->buf != strbuf_slopbuf)
05d292b2 (kx 2023-03-24 03:51:10 +0300 77) sb->buf[len] = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 78) else
05d292b2 (kx 2023-03-24 03:51:10 +0300 79) if( !strbuf_slopbuf[0] ) sb->fatal( "BUG: strbuf_slopbuf[0] = '\0'" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 80) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 81)
05d292b2 (kx 2023-03-24 03:51:10 +0300 82) #define strbuf_reset(sb) strbuf_setlen(sb, 0)
05d292b2 (kx 2023-03-24 03:51:10 +0300 83)
05d292b2 (kx 2023-03-24 03:51:10 +0300 84)
05d292b2 (kx 2023-03-24 03:51:10 +0300 85) /***************************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 86) BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
05d292b2 (kx 2023-03-24 03:51:10 +0300 87) @cond: the compile-time condition which must be true.
05d292b2 (kx 2023-03-24 03:51:10 +0300 88)
05d292b2 (kx 2023-03-24 03:51:10 +0300 89) Your compile will fail if the condition isn't true, or can't be evaluated
05d292b2 (kx 2023-03-24 03:51:10 +0300 90) by the compiler. This can be used in an expression: its value is "0".
05d292b2 (kx 2023-03-24 03:51:10 +0300 91)
05d292b2 (kx 2023-03-24 03:51:10 +0300 92) Example:
05d292b2 (kx 2023-03-24 03:51:10 +0300 93) #define foo_to_char(foo) \
05d292b2 (kx 2023-03-24 03:51:10 +0300 94) ((char *)(foo) \
05d292b2 (kx 2023-03-24 03:51:10 +0300 95) + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
05d292b2 (kx 2023-03-24 03:51:10 +0300 96) ***************************************************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 97) #define BUILD_ASSERT_OR_ZERO(cond) \
05d292b2 (kx 2023-03-24 03:51:10 +0300 98) (sizeof(char [1 - 2*!(cond)]) - 1)
05d292b2 (kx 2023-03-24 03:51:10 +0300 99)
05d292b2 (kx 2023-03-24 03:51:10 +0300 100) #define SWAP(a, b) \
05d292b2 (kx 2023-03-24 03:51:10 +0300 101) do { \
05d292b2 (kx 2023-03-24 03:51:10 +0300 102) void *_swap_a_ptr = &(a); \
05d292b2 (kx 2023-03-24 03:51:10 +0300 103) void *_swap_b_ptr = &(b); \
05d292b2 (kx 2023-03-24 03:51:10 +0300 104) unsigned char _swap_buffer[sizeof(a)]; \
05d292b2 (kx 2023-03-24 03:51:10 +0300 105) memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
05d292b2 (kx 2023-03-24 03:51:10 +0300 106) memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a) + \
05d292b2 (kx 2023-03-24 03:51:10 +0300 107) BUILD_ASSERT_OR_ZERO(sizeof(a) == sizeof(b))); \
05d292b2 (kx 2023-03-24 03:51:10 +0300 108) memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
05d292b2 (kx 2023-03-24 03:51:10 +0300 109) } while (0)
05d292b2 (kx 2023-03-24 03:51:10 +0300 110)
05d292b2 (kx 2023-03-24 03:51:10 +0300 111) static inline void strbuf_swap( struct strbuf *a, struct strbuf *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300 112) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 113) SWAP(*a, *b);
05d292b2 (kx 2023-03-24 03:51:10 +0300 114) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 115)
05d292b2 (kx 2023-03-24 03:51:10 +0300 116)
05d292b2 (kx 2023-03-24 03:51:10 +0300 117) extern void strbuf_ltrim( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 118) extern void strbuf_rtrim( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 119) extern void strbuf_trim( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 120)
05d292b2 (kx 2023-03-24 03:51:10 +0300 121) #ifndef is_dir_sep
05d292b2 (kx 2023-03-24 03:51:10 +0300 122) static inline int is_dir_sep( int c )
05d292b2 (kx 2023-03-24 03:51:10 +0300 123) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 124) return c == '/';
05d292b2 (kx 2023-03-24 03:51:10 +0300 125) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 126) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300 127) static inline int is_absolute_path( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 128) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 129) return is_dir_sep( path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 130) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 131)
05d292b2 (kx 2023-03-24 03:51:10 +0300 132) extern void strbuf_trim_trailing_dir_sep( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 133) extern void strbuf_trim_trailing_newline( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 134)
05d292b2 (kx 2023-03-24 03:51:10 +0300 135) extern int strbuf_cmp( const struct strbuf *a, const struct strbuf *b );
05d292b2 (kx 2023-03-24 03:51:10 +0300 136)
05d292b2 (kx 2023-03-24 03:51:10 +0300 137)
05d292b2 (kx 2023-03-24 03:51:10 +0300 138) /* Adding data to the buffer */
05d292b2 (kx 2023-03-24 03:51:10 +0300 139)
05d292b2 (kx 2023-03-24 03:51:10 +0300 140) extern void strbuf_add( struct strbuf *sb, const void *data, size_t len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 141) extern void strbuf_addbuf( struct strbuf *sb, const struct strbuf *sb2 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 142) extern void strbuf_addbuf_percentquote( struct strbuf *dst, const struct strbuf *src );
05d292b2 (kx 2023-03-24 03:51:10 +0300 143)
05d292b2 (kx 2023-03-24 03:51:10 +0300 144)
05d292b2 (kx 2023-03-24 03:51:10 +0300 145) /* Add a single ASCII character to the buffer. */
05d292b2 (kx 2023-03-24 03:51:10 +0300 146) static inline void strbuf_addch( struct strbuf *sb, int c )
05d292b2 (kx 2023-03-24 03:51:10 +0300 147) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 148) if( !strbuf_avail(sb) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 149) strbuf_grow(sb, 1);
05d292b2 (kx 2023-03-24 03:51:10 +0300 150) sb->buf[sb->len++] = c;
05d292b2 (kx 2023-03-24 03:51:10 +0300 151) sb->buf[sb->len] = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 152) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 153)
05d292b2 (kx 2023-03-24 03:51:10 +0300 154) /* Add n ASCII characters to the buffer. */
05d292b2 (kx 2023-03-24 03:51:10 +0300 155) extern void strbuf_addchars( struct strbuf *sb, int c, size_t n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 156)
05d292b2 (kx 2023-03-24 03:51:10 +0300 157) /* Add a NUL-terminated string to the buffer. */
05d292b2 (kx 2023-03-24 03:51:10 +0300 158) static inline void strbuf_addstr( struct strbuf *sb, const char *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300 159) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 160) strbuf_add( sb, (const void *)s, strlen(s) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 161) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 162)
05d292b2 (kx 2023-03-24 03:51:10 +0300 163) extern void strbuf_vaddf( struct strbuf *sb, const char *fmt, va_list ap );
05d292b2 (kx 2023-03-24 03:51:10 +0300 164) extern void strbuf_addf( struct strbuf *sb, const char *fmt, ... );
05d292b2 (kx 2023-03-24 03:51:10 +0300 165)
05d292b2 (kx 2023-03-24 03:51:10 +0300 166) extern size_t strbuf_fread( struct strbuf *sb, FILE *fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 167) extern size_t strbuf_env_fread( struct strbuf *sb, FILE *fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 168) extern size_t strbuf_fwrite( struct strbuf *sb, FILE *fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 169)
05d292b2 (kx 2023-03-24 03:51:10 +0300 170) extern ssize_t strbuf_read( struct strbuf *sb, int fd, size_t hint );
05d292b2 (kx 2023-03-24 03:51:10 +0300 171) extern ssize_t strbuf_write( struct strbuf *sb, int fd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 172)
05d292b2 (kx 2023-03-24 03:51:10 +0300 173)
05d292b2 (kx 2023-03-24 03:51:10 +0300 174) /* XML/HTML quoted: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 175) extern void strbuf_addstr_xml_quoted( struct strbuf *sb, const char *s );
05d292b2 (kx 2023-03-24 03:51:10 +0300 176) extern void strbuf_addstr_html_quoted( struct strbuf *sb, const char *s );
05d292b2 (kx 2023-03-24 03:51:10 +0300 177)
05d292b2 (kx 2023-03-24 03:51:10 +0300 178) /* urlencode: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 179) typedef int (*char_predicate)(char ch);
05d292b2 (kx 2023-03-24 03:51:10 +0300 180)
05d292b2 (kx 2023-03-24 03:51:10 +0300 181) extern int is_rfc3986_unreserved( char ch );
05d292b2 (kx 2023-03-24 03:51:10 +0300 182) extern int is_rfc3986_reserved_or_unreserved( char ch );
05d292b2 (kx 2023-03-24 03:51:10 +0300 183)
05d292b2 (kx 2023-03-24 03:51:10 +0300 184) extern void strbuf_addstr_urlencode( struct strbuf *sb, const char *name, char_predicate allow_unencoded_fn );
05d292b2 (kx 2023-03-24 03:51:10 +0300 185)
05d292b2 (kx 2023-03-24 03:51:10 +0300 186)
05d292b2 (kx 2023-03-24 03:51:10 +0300 187) extern void strbuf_humanise_bytes( struct strbuf *sb, off_t bytes );
05d292b2 (kx 2023-03-24 03:51:10 +0300 188) extern void strbuf_humanise_rate( struct strbuf *sb, off_t bytes );
05d292b2 (kx 2023-03-24 03:51:10 +0300 189)
05d292b2 (kx 2023-03-24 03:51:10 +0300 190)
05d292b2 (kx 2023-03-24 03:51:10 +0300 191) extern int is_directory( const char *path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 192)
05d292b2 (kx 2023-03-24 03:51:10 +0300 193) extern void strbuf_selfdir( struct strbuf *sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 194) extern void strbuf_relpath( struct strbuf *sb, const char *path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 195) extern void strbuf_abspath( struct strbuf *sb, const char *path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 196)
05d292b2 (kx 2023-03-24 03:51:10 +0300 197)
05d292b2 (kx 2023-03-24 03:51:10 +0300 198) #ifdef __cplusplus
05d292b2 (kx 2023-03-24 03:51:10 +0300 199) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 200) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300 201)
05d292b2 (kx 2023-03-24 03:51:10 +0300 202) #endif /* __STRBUF_H */