📄 strbuf.c
字号:
/* * Copyright (c) 1997, 1998, 1999, 2000, 2002, 2005 * Tama Communications Corporation * * This file is part of GNU GLOBAL. * * GNU GLOBAL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GNU GLOBAL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <ctype.h>#ifdef STDC_HEADERS#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include "die.h"#include "strbuf.h"#ifndef isblank#define isblank(c) ((c) == ' ' || (c) == '\t')#endif/*String buffer: usage and memory status [xxx]: string buffer 'v': current pointerFunction call Memory status---------------------------------------------------------- (not exist) vsb = strbuf_open(0); [] vstrbuf_putc(sb, 'a'); [a] vchar *s = strbuf_value(sb); [a\0] s == "a" vstrbuf_puts(sb, "bc"); [abc] vchar *s = strbuf_value(sb); [abc\0] s == "abc" vint len = strbuf_getlen(sb); [abc\0] len == 3 vstrbuf_reset(sb); [abc\0] vint len = strbuf_getlen(sb); [abc\0] len == 0 vstrbuf_puts(sb, "XY"); [XYc\0] vchar *s = strbuf_value(sb); [XY\0] s == "XY"fp = fopen("/etc/passwd", "r"); vchar *s = strbuf_fgets(sb, fp, 0) [root:*:0:0:Charlie &:/root:/bin/csh\0]fclose(fp) s == "root:*:0:0:Charlie &:/root:/bin/csh"strbuf_close(sb); (not exist)*/static void print_and_abort (void);void (*strbuf_alloc_failed_handler) (void) = print_and_abort;static voidprint_and_abort(void){ die("short of memory.");}#ifdef STRBUF_LINKSTRBUF top;/* * strbuf_dump: dump string buffers */voidstrbuf_dump(msg) const char *msg;{ STRBUF *sb; int i = 0; long total = 0, used = 0; fprintf(stderr, "[%s/%s]\n", progname, msg); for (sb = top.next; sb && sb != ⊤ sb = sb->next) { char *p = strbuf_value(sb); char *end = p + strbuf_getlen(sb); *sb->curp = 0; fprintf(stderr, "(%d)\tsize=%d used=%d ", ++i, sb->sbufsize, strbuf_getlen(sb)); total += sb->sbufsize; used += strbuf_getlen(sb); for (; p < end; p += strlen(p) + 1) fprintf(stderr, "[%s]", p); fputc('\n', stderr); } fprintf(stderr, "Total %ld bytes, used %ld bytes\n", total, used);}#endif/* * __strbuf_expandbuf: expand buffer so that afford to the length data at least. * * i) sb STRBUF structure * i) length required room */void__strbuf_expandbuf(sb, length) STRBUF *sb; int length;{ int count = sb->curp - sb->sbuf; int newsize = sb->sbufsize + (length > EXPANDSIZE ? length : EXPANDSIZE); char *newbuf; if (sb->alloc_failed) return; newbuf = (char *)realloc(sb->sbuf, newsize + 1); if (newbuf == NULL) { (*strbuf_alloc_failed_handler)(); sb->alloc_failed = 1; return; } sb->sbufsize = newsize; sb->sbuf = newbuf; sb->curp = sb->sbuf + count; sb->endp = sb->sbuf + sb->sbufsize;}/* * strbuf_open: open string buffer. * * i) init initial buffer size * if 0 is specified then use default value. * r) sb STRBUF structure */STRBUF *strbuf_open(init) int init;{ STRBUF *sb = (STRBUF *)calloc(sizeof(STRBUF), 1); if (sb == NULL) { (*strbuf_alloc_failed_handler)(); return NULL; } sb->sbufsize = (init > 0) ? init : INITIALSIZE; if (!(sb->sbuf = (char *)malloc(sb->sbufsize + 1))) { (*strbuf_alloc_failed_handler)(); (void)free(sb); return NULL; } sb->curp = sb->sbuf; sb->endp = sb->sbuf + sb->sbufsize;#ifdef STRBUF_LINK if (top.next == NULL) { top.next = top.prev = sb; sb->next = sb->prev = ⊤ } else { sb->next = ⊤ sb->prev = top.prev; top.prev->next = sb; top.prev = sb; }#endif return sb;}/* * strbuf_clear: clear static string buffer. * * i) sb statically defined string buffer * * This function is used for the initializing of static string buffer. * For the detail, see 'STATIC_STRBUF(sb)' macro in strbuf.h. */voidstrbuf_clear(sb) STRBUF *sb;{ if (sb == NULL) die("NULL string buffer. (strbuf_clear)"); if (strbuf_empty(sb)) { sb->sbufsize = INITIALSIZE; if (!(sb->sbuf = (char *)malloc(sb->sbufsize + 1))) { (*strbuf_alloc_failed_handler)(); return; } sb->curp = sb->sbuf; sb->endp = sb->sbuf + sb->sbufsize; } else { strbuf_reset(sb); }}/* * strbuf_nputs: Put string with length * * i) sb statically defined string buffer * i) s string * i) len length of string */voidstrbuf_nputs(sb, s, len) STRBUF *sb; const char *s; int len;{ if (!sb->alloc_failed && len > 0) { if (sb->curp + len > sb->endp) __strbuf_expandbuf(sb, len); while (len-- > 0) *sb->curp++ = *s++; }}/* * strbuf_puts: Put string * * i) sb statically defined string buffer * i) s string */voidstrbuf_puts(sb, s) STRBUF *sb; const char *s;{ if (!sb->alloc_failed) { while (*s) { if (sb->curp >= sb->endp) __strbuf_expandbuf(sb, 0); *sb->curp++ = *s++; } }}/* * strbuf_puts_nl: Put string with a new line * * i) sb statically defined string buffer * i) s string */voidstrbuf_puts_nl(sb, s) STRBUF *sb; const char *s;{ if (!sb->alloc_failed) { while (*s) { if (sb->curp >= sb->endp) __strbuf_expandbuf(sb, 0); *sb->curp++ = *s++; } if (sb->curp >= sb->endp) __strbuf_expandbuf(sb, 0); *sb->curp++ = '\n'; }}/* * strbuf_putn: put digit string at the last of buffer. * * i) sb STRBUF structure * i) n number */voidstrbuf_putn(sb, n) STRBUF *sb; int n;{ if (n == 0) { strbuf_putc(sb, '0'); } else { char num[128]; int i = 0; while (n) { if (i >= sizeof(num)) die("Too big integer value."); num[i++] = n % 10 + '0'; n = n / 10; } while (--i >= 0) strbuf_putc(sb, num[i]); }}/* * strbuf_unputc: remove specified char from the last of buffer * * i) sb STRBUF structure * i) c character * r) 0: do nothing, 1: removed */intstrbuf_unputc(sb, c) STRBUF *sb; int c;{ if (sb->curp > sb->sbuf && *(sb->curp - 1) == c) { sb->curp--; return 1; } return 0;}/* * strbuf_value: return the content of string buffer. * * i) sb STRBUF structure * r) string */char *strbuf_value(sb) STRBUF *sb;{ *sb->curp = 0; return sb->sbuf;}/* * strbuf_trim: trim following blanks. * * i) sb STRBUR structure */voidstrbuf_trim(sb) STRBUF *sb;{ char *p = sb->curp; while (p > sb->sbuf && isblank(*(p - 1))) *--p = 0; sb->curp = p;}/* * strbuf_fgets: read whole record into string buffer * * o) sb string buffer * i) ip input stream * i) flags flags * STRBUF_NOCRLF remove last '\n' if exist. * STRBUF_APPEND append next record to existing data * r) record buffer (NULL at end of file) * * Returned buffer has whole record. * The buffer end with '\0'.If STRBUF_NOCRLF is set then buffer doesn't * include '\r' and '\n'. */char *strbuf_fgets(sb, ip, flags) STRBUF *sb; FILE *ip; int flags;{ if (!(flags & STRBUF_APPEND)) strbuf_reset(sb); if (sb->curp >= sb->endp) __strbuf_expandbuf(sb, EXPANDSIZE); /* expand buffer */ if (sb->alloc_failed) return sb->sbuf; for (;;) { if (!fgets(sb->curp, sb->endp - sb->curp, ip)) { if (sb->curp == sb->sbuf) return NULL; break; } sb->curp += strlen(sb->curp); if (*(sb->curp - 1) == '\n') break; else if (feof(ip)) { return sb->sbuf; } __strbuf_expandbuf(sb, EXPANDSIZE); /* expand buffer */ if (sb->alloc_failed) return sb->sbuf; } if (flags & STRBUF_NOCRLF) { if (*(sb->curp - 1) == '\n') *(--sb->curp) = 0; if (*(sb->curp - 1) == '\r') *(--sb->curp) = 0; } return sb->sbuf;}/* * strbuf_sprintf: do sprintf into string buffer. * * i) sb STRBUF structure * i) s similar to sprintf() * Currently the following format is supported. * %s, %d, %<number>d, %<number>s, %-<number>d, %-<number>s */void#ifdef HAVE_STDARG_Hstrbuf_sprintf(STRBUF *sb, const char *s, ...)#elsestrbuf_sprintf(sb, s, va_alist) STRBUF *sb; const char *s; va_dcl#endif{ va_list ap;#ifdef HAVE_STDARG_H va_start(ap, s);#else va_start(ap);#endif if (sb->alloc_failed) return; for (; *s; s++) { /* * Put the before part of '%'. */ { const char *p; for (p = s; *p && *p != '%'; p++) ; if (p > s) { strbuf_nputs(sb, s, p - s); s = p; } } if (*s == '\0') break; if (*s == '%') { int c = (unsigned char)*++s; /* * '%%' means '%'. */ if (c == '%') { strbuf_putc(sb, c); } /* * If the optional number is specified then * we forward the job to snprintf(3). * o %<number>d * o %<number>s * o %-<number>d * o %-<number>s */ else if (isdigit(c) || (c == '-' && isdigit((unsigned char)*(s + 1)))) { char format[32], buf[1024]; int i = 0; format[i++] = '%'; if (c == '-') format[i++] = *s++; while (isdigit((unsigned char)*s)) format[i++] = *s++; format[i++] = c = *s; format[i] = '\0'; if (c == 'd' || c == 'x') snprintf(buf, sizeof(buf), format, va_arg(ap, int)); else if (c == 's') snprintf(buf, sizeof(buf), format, va_arg(ap, char *)); else die("Unsupported control character '%c'.", c); strbuf_puts(sb, buf); } else if (c == 's') { strbuf_puts(sb, va_arg(ap, char *)); } else if (c == 'd') { strbuf_putn(sb, va_arg(ap, int)); } else { die("Unsupported control character '%c'.", c); } } } va_end(ap);}/* * strbuf_close: close string buffer. * * i) sb STRBUF structure */voidstrbuf_close(sb) STRBUF *sb;{#ifdef STRBUF_LINK sb->prev->next = sb->next; sb->next->prev = sb->prev;#endif if (sb->name) (void)free(sb->name); (void)free(sb->sbuf); (void)free(sb);}/* * Temporary string buffer for general purpose. * * Usage: * * STRBUF *sbt = strbuf_open_tempbuf(); * .... * strbuf_puts(sbtemp, "xxx"); * ... * strbuf_release_tempbuf(sbt); * */int used = 0;STRBUF *strbuf_open_tempbuf(void){ STATIC_STRBUF(sb); if (used) die("Internal error: temporary string buffer is already used."); used = 1; strbuf_clear(sb); return sb;}voidstrbuf_release_tempbuf(sb) STRBUF *sb;{ used = 0;}#ifdef STRBUF_LINK/* * strbuf_setname: set name to specified string buffer. * * i) sb STRBUF structure * i) name name */voidstrbuf_setname(sb, name) STRBUF *sb; const char *name;{ char *p = strdup(name); if (p == NULL) { (*strbuf_alloc_failed_handler)(); sb->alloc_failed = 1; return; } if (sb->name) (void)free(sb->name); sb->name = p;}/* * strbuf_getbuf: get named buffer * * i) name name of buffer * r) STRBUF structure */STRBUF *strbuf_getbuf(name) const char *name;{ STRBUF *sb; for (sb = top.next; sb && sb != ⊤ sb = sb->next) if (sb->name && !strcmp(name, sb->name)) return sb; return NULL;}/* * strbuf_closeall: close all string buffer. */voidstrbuf_closeall(void){ while (top.next != &top) strbuf_close(top.next); top.next = top.prev = NULL;}#endif /* STRBUF_LINK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -