📄 htstring.c
字号:
if (!delims) delims = " ;,=" ; if (!bracks) bracks = "<\"" ; get_blanks = (BOOL) (!strchr(delims,' ') && !strchr(bracks,' ')); get_comments = (BOOL) (strchr(bracks,'(') != NULL); skip_comments = (BOOL) (!get_comments && !strchr(delims,'(') && !get_blanks);#define skipWHITE(c) (!get_blanks && WHITE(c)) while (*p && skipWHITE(*p)) p++; /* Strip white space */ if (!*p) { *pstr = p; if (found) *found = '\0'; return NULL; /* No first field */ } while (1) { /* Strip white space and other delimiters */ while (*p && (skipWHITE(*p) || strchr(delims,*p))) p++; if (!*p) { *pstr = p; if (found) *found = *(p-1); return NULL; /* No field */ } if (*p == '(' && (skip_comments || get_comments)) { /* Comment */ int comment_level = 0; if (get_comments && !start) start = p+1; for(;*p && (*p!=')' || --comment_level>0); p++) { if (*p == '(') comment_level++; else if (*p == '"') { /* quoted field within Comment */ for(p++; *p && *p!='"'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ if (!*p) break; /* (invalid) end of string found, leave */ } if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ } if (get_comments) break; if (*p) p++; if (get_closing_char_too) { if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) { break; } else get_closing_char_too = (BOOL) (strchr(bracks,*p) != NULL); } } else if (strchr(bracks,*p)) { /* quoted or bracketed field */ switch (*p) { case '<': closer = '>'; break; case '[': closer = ']'; break; case '{': closer = '}'; break; case ':': closer = ';'; break; default: closer = *p; } if (!start) start = ++p; for(;*p && *p!=closer; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ if (get_closing_char_too) { p++; if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) { break; } else get_closing_char_too = (BOOL) (strchr(bracks,*p) != NULL); } else break; /* kr95-10-9: needs to stop here */ } else { /* Spool field */ if (!start) start = p; while(*p && !skipWHITE(*p) && !strchr(bracks,*p) && !strchr(delims,*p)) p++; if (*p && strchr(bracks,*p)) { get_closing_char_too = TRUE; } else { if (*p=='(' && skip_comments) { *pstr = p; HTNextTok(pstr, NULL, "(", found); /* Advance pstr */ *p = '\0'; if (*pstr && **pstr) (*pstr)++; return start; } break; /* Got it */ } } } if (found) *found = *p; if (*p) *p++ = '\0'; *pstr = p; return start;}PRIVATE char *HTAlloc ARGS2(char *, ptr, size_t, length){ if (ptr != 0) ptr = (char *)realloc(ptr, length); else ptr = (char *)malloc(length); if (ptr == 0) outofmem(__FILE__, "HTAlloc"); return ptr;}/* * If SAVE_TIME_NOT_SPACE is defined, StrAllocVsprintf will hang on to * its temporary string buffers instead of allocating and freeing them * in each invocation. They only grow and never shrink, and won't be * cleaned up on exit. - kw */#if defined(_REENTRANT) || defined(_THREAD_SAFE) || defined(LY_FIND_LEAKS)#undef SAVE_TIME_NOT_SPACE#endif/* * Replacement for sprintf, allocates buffer on the fly according to what's * needed for its arguments. Unlike sprintf, this always concatenates to the * destination buffer, so we do not have to provide both flavors. */typedef enum { Flags, Width, Prec, Type, Format } PRINTF;#define VA_INTGR(type) ival = va_arg((*ap), type)#define VA_FLOAT(type) fval = va_arg((*ap), type)#define VA_POINT(type) pval = (void *)va_arg((*ap), type)#define NUM_WIDTH 10 /* allow for width substituted for "*" in "%*s" */ /* also number of chars assumed to be needed in addition to a given precision in floating point formats */#define GROW_EXPR(n) (((n) * 3) / 2)#define GROW_SIZE 256PUBLIC_IF_FIND_LEAKS char * StrAllocVsprintf ARGS4( char **, pstr, size_t, dst_len, CONST char *, fmt, va_list *, ap){#ifdef SAVE_TIME_NOT_SPACE static size_t tmp_len = 0; static size_t fmt_len = 0; static char *tmp_ptr = NULL; static char *fmt_ptr = NULL;#else size_t tmp_len = GROW_SIZE; char *tmp_ptr = 0; char *fmt_ptr;#endif /* SAVE_TIME_NOT_SPACE */ size_t have, need; char *dst_ptr = *pstr; CONST char *format = fmt; if (fmt == 0 || *fmt == '\0') return 0;#ifdef USE_VASPRINTF if (pstr && !dst_len) { if (*pstr) FREE(*pstr); if (vasprintf(pstr, fmt, *ap) >= 0) { mark_malloced(*pstr, strlen(*pstr)+1); return(*pstr); } }#endif /* USE_VASPRINTF */ need = strlen(fmt) + 1;#ifdef SAVE_TIME_NOT_SPACE if (!fmt_ptr || fmt_len < need*NUM_WIDTH) { fmt_ptr = HTAlloc(fmt_ptr, fmt_len = need*NUM_WIDTH); } if (!tmp_ptr || tmp_len < GROW_SIZE) { tmp_ptr = HTAlloc(tmp_ptr, tmp_len = GROW_SIZE); }#else if ((fmt_ptr = malloc(need*NUM_WIDTH)) == 0 || (tmp_ptr = malloc(tmp_len)) == 0) { outofmem(__FILE__, "StrAllocVsprintf"); }#endif /* SAVE_TIME_NOT_SPACE */ if (dst_ptr == 0) { dst_ptr = HTAlloc(dst_ptr, have = GROW_SIZE + need); } else { have = strlen(dst_ptr) + 1; need += dst_len; if (have < need) dst_ptr = HTAlloc(dst_ptr, have = GROW_SIZE + need); } while (*fmt != '\0') { if (*fmt == '%') { static char dummy[] = ""; PRINTF state = Flags; char *pval = dummy; /* avoid const-cast */ double fval = 0.0; int done = FALSE; int ival = 0; int prec = -1; int type = 0; int used = 0; int width = -1; size_t f = 0; fmt_ptr[f++] = *fmt; while (*++fmt != '\0' && !done) { fmt_ptr[f++] = *fmt; if (isdigit(UCH(*fmt))) { int num = *fmt - '0'; if (state == Flags && num != 0) state = Width; if (state == Width) { if (width < 0) width = 0; width = (width * 10) + num; } else if (state == Prec) { if (prec < 0) prec = 0; prec = (prec * 10) + num; } } else if (*fmt == '*') { VA_INTGR(int); if (state == Flags) state = Width; if (state == Width) { width = ival; } else if (state == Prec) { prec = ival; } sprintf(&fmt_ptr[--f], "%d", ival); f = strlen(fmt_ptr); } else if (isalpha(UCH(*fmt))) { done = TRUE; switch (*fmt) { case 'Z': /* FALLTHRU */ case 'h': /* FALLTHRU */ case 'l': /* FALLTHRU */ case 'L': /* FALLTHRU */ done = FALSE; type = *fmt; break; case 'o': /* FALLTHRU */ case 'i': /* FALLTHRU */ case 'd': /* FALLTHRU */ case 'u': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ if (type == 'l') VA_INTGR(long); else if (type == 'Z') VA_INTGR(size_t); else VA_INTGR(int); used = 'i'; break; case 'f': /* FALLTHRU */ case 'e': /* FALLTHRU */ case 'E': /* FALLTHRU */ case 'g': /* FALLTHRU */ case 'G': /* FALLTHRU */ VA_FLOAT(double); used = 'f'; break; case 'c': VA_INTGR(int); used = 'c'; break; case 's': VA_POINT(char *); if (prec < 0) prec = strlen(pval); used = 's'; break; case 'p': VA_POINT(void *); used = 'p'; break; case 'n': VA_POINT(int *); used = 0; break; default: CTRACE((tfp, "unknown format character '%c' in %s\n", *fmt, format)); break; } } else if (*fmt == '.') { state = Prec; } else if (*fmt == '%') { done = TRUE; used = '%'; } } fmt_ptr[f] = '\0'; if (prec > 0) { switch (used) { case 'f': if (width < prec + NUM_WIDTH) width = prec + NUM_WIDTH; /* FALLTHRU */ case 'i': /* FALLTHRU */ case 'p': if (width < prec + 2) width = prec + 2; /* leading sign/space/zero, "0x" */ break; case 'c': break; case '%': break; default: if (width < prec) width = prec; break; } } if (width >= (int)tmp_len) { tmp_len = GROW_EXPR(tmp_len + width); tmp_ptr = HTAlloc(tmp_ptr, tmp_len); } switch (used) { case 'i': case 'c': sprintf(tmp_ptr, fmt_ptr, ival); break; case 'f': sprintf(tmp_ptr, fmt_ptr, fval); break; default: sprintf(tmp_ptr, fmt_ptr, pval); break; } need = dst_len + strlen(tmp_ptr) + 1; if (need >= have) { dst_ptr = HTAlloc(dst_ptr, have = GROW_EXPR(need)); } strcpy(dst_ptr + dst_len, tmp_ptr); dst_len += strlen(tmp_ptr); } else { if ((dst_len + 2) >= have) { dst_ptr = HTAlloc(dst_ptr, (have += GROW_SIZE)); } dst_ptr[dst_len++] = *fmt++; } }#ifndef SAVE_TIME_NOT_SPACE FREE(tmp_ptr); FREE(fmt_ptr);#endif dst_ptr[dst_len] = '\0'; if (pstr) *pstr = dst_ptr; return (dst_ptr);}#undef SAVE_TIME_NOT_SPACE/* * Replacement for sprintf, allocates buffer on the fly according to what's * needed for its arguments. Unlike sprintf, this always concatenates to the * destination buffer. *//* Note: if making changes, also check the memory tracking version * LYLeakHTSprintf in LYLeaks.c. - kw */#ifdef HTSprintf /* if hidden by LYLeaks stuff */#undef HTSprintf#endif#if ANSI_VARARGSPUBLIC char * HTSprintf (char ** pstr, CONST char * fmt, ...)#elsePUBLIC char * HTSprintf (va_alist) va_dcl#endif{ char *result = 0; size_t inuse = 0; va_list ap; LYva_start(ap,fmt); {#if !ANSI_VARARGS char ** pstr = va_arg(ap, char **); CONST char * fmt = va_arg(ap, CONST char *);#endif if (pstr != 0 && *pstr != 0) inuse = strlen(*pstr); result = StrAllocVsprintf(pstr, inuse, fmt, &ap); } va_end(ap); return (result);}/* * Replacement for sprintf, allocates buffer on the fly according to what's * needed for its arguments. Like sprintf, this always resets the destination * buffer. *//* Note: if making changes, also check the memory tracking version * LYLeakHTSprintf0 in LYLeaks.c. - kw */#ifdef HTSprintf0 /* if hidden by LYLeaks stuff */#undef HTSprintf0#endif#if ANSI_VARARGSPUBLIC char * HTSprintf0 (char ** pstr, CONST char * fmt, ...)#elsePUBLIC char * HTSprintf0 (va_alist) va_dcl#endif{ char *result = 0; va_list ap; LYva_start(ap,fmt); {#if !ANSI_VARARGS char ** pstr = va_arg(ap, char **); CONST char * fmt = va_arg(ap, CONST char *);#endif#ifdef USE_VASPRINTF if (pstr) { if (*pstr) FREE(*pstr); if (vasprintf(pstr, fmt, ap) >= 0) /* else call outofmem?? */ mark_malloced(*pstr, strlen(*pstr)+1); result = *pstr; } else#endif /* USE_VASPRINTF */ result = StrAllocVsprintf(pstr, 0, fmt, &ap); } va_end(ap); return (result);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -