⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_string.c

📁 linux subdivision ying gai ke yi le ba
💻 C
字号:
/*    String utility functions   Copyright (C) 1999-2003, Joe Orton <joe@manyfish.co.uk>   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.      This library 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   Library General Public License for more details.   You should have received a copy of the GNU Library General Public   License along with this library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   MA 02111-1307, USA*/#include "config.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <ctype.h> /* for isprint() etc in ne_strclean() */#include "ne_alloc.h"#include "ne_string.h"char *ne_token(char **str, char separator){    char *ret = *str, *pnt = strchr(*str, separator);    if (pnt) {	*pnt = '\0';	*str = pnt + 1;    } else {	/* no separator found: return end of string. */	*str = NULL;    }        return ret;}char *ne_qtoken(char **str, char separator, const char *quotes){    char *pnt, *ret = NULL;    for (pnt = *str; *pnt != '\0'; pnt++) {	char *quot = strchr(quotes, *pnt);		if (quot) {	    char *qclose = strchr(pnt+1, *quot);	    	    if (!qclose) {		/* no closing quote: invalid string. */		return NULL;	    }	    	    pnt = qclose;	} else if (*pnt == separator) {	    /* found end of token. */	    *pnt = '\0';	    ret = *str;	    *str = pnt + 1;	    return ret;	}    }    /* no separator found: return end of string. */    ret = *str;    *str = NULL;    return ret;}char *ne_shave(char *str, const char *whitespace){    char *pnt, *ret = str;    while (*ret != '\0' && strchr(whitespace, *ret) != NULL) {	ret++;    }    /* pnt points at the NUL terminator. */    pnt = &ret[strlen(ret)];        while (pnt > ret && strchr(whitespace, *(pnt-1)) != NULL) {	pnt--;    }    *pnt = '\0';    return ret;}/* TODO: deprecate all these and use ne_token() instead. */char **split_string(const char *str, const char separator,		     const char *quotes, const char *whitespace) {    return split_string_c(str, separator, quotes, whitespace, NULL);}char **split_string_c(const char *str, const char separator,		      const char *quotes, const char *whitespace,		      int *give_count) {    char **comps;    const char *pnt, *quot = NULL,	*start, *end; /* The start of the current component */    int count, /* The number of components */	iswhite, /* is it whitespace */	issep, /* is it the separator */	curr, /* current component index */	length, /* length of component */	leading_wspace; /* in leading whitespace still? */    /* Inefficient, but easier - first off, count the number of      * components we have. */    count = 1;    for (pnt = str; *pnt!='\0'; pnt++) {	if (quotes != NULL) {	    quot = strchr(quotes, *pnt);	}	if (quot != NULL) {	    /* We found a quote, so skip till the next quote */	    for (pnt++; (*pnt!=*quot) && (*pnt!='\0'); pnt++)		/* nullop */;	} else if (*pnt == separator) {	    count++;	}    }    if (give_count) {	/* Write the count */	*give_count = count;    }    /* Now, have got the number of components.     * Allocate the comps array. +1 for the NULL */    comps = ne_malloc(sizeof(char *) * (count + 1));    comps[count] = NULL;        quot = end = start = NULL;    curr = 0;    leading_wspace = 1;    /* Now fill in the array */    for (pnt = str; *pnt != '\0'; pnt++) {	/* What is the current character - quote, whitespace, separator? */	if (quotes != NULL) {	    quot = strchr(quotes, *pnt);	}	iswhite = (whitespace!=NULL) && 	    (strchr(whitespace, *pnt) != NULL);	issep = (*pnt == separator);	/* What to do? */	if (leading_wspace) {	    if (quot!=NULL) {		/* Quoted bit */		start = pnt;		length = 1;		leading_wspace = 0;	    } else if (issep) {		/* Zero-length component */		comps[curr++] = ne_strdup("");	    } else if (!iswhite) {		start = end = pnt;		length = 1;		leading_wspace = 0;	    }	} else {	    if (quot!=NULL) {		/* Quoted bit */		length++;	    } else if (issep) {		/* End of component - enter it into the array */		length = (end - start) + 1;		comps[curr] = ne_malloc(length+1);		memcpy(comps[curr], start, length);		comps[curr][length] = '\0';		curr++;		leading_wspace = 1;	    } else if (!iswhite) {		/* Not whitespace - update end marker */		end = pnt;	    }	}	if (quot != NULL) {	    /* Skip to closing quote */	    for (pnt++; *pnt!=*quot && *pnt != '\0'; ++pnt)		/* nullop */;	    /* Last non-wspace char is closing quote */	    end = pnt;	}    }    /* Handle final component */    if (leading_wspace) {	comps[curr] = ne_strdup("");    } else {	/* End of component - enter it into the array */	length = (end - start) + 1;	comps[curr] = ne_malloc(length+1);	memcpy(comps[curr], start, length);	comps[curr][length] = '\0';    }    return comps;}char **pair_string(const char *str, const char compsep, const char kvsep, 		 const char *quotes, const char *whitespace) {    char **comps, **pairs, *split;    int count = 0, n, length;    comps = split_string_c(str, compsep, quotes, whitespace, &count);    /* Allocate space for 2* as many components as split_string returned,     * +2 for the NULLS. */    pairs = ne_malloc((2*count+2) * sizeof(char *));    if (pairs == NULL) {	return NULL;    }    for (n = 0; n < count; n++) {	/* Find the split */	split = strchr(comps[n], kvsep);	if (split == NULL) {	    /* No seperator found */	    length = strlen(comps[n]);	} else {	    length = split-comps[n];	}	/* Enter the key into the array */	pairs[2*n] = comps[n];	/* Null-terminate the key */	pairs[2*n][length] = '\0';	pairs[2*n+1] = split?(split + 1):NULL;    }    ne_free(comps);    pairs[2*count] = pairs[2*count+1] = NULL;        return pairs;}void split_string_free(char **components) {    char **pnt = components;    while (*pnt != NULL) {	ne_free(*pnt);	pnt++;    }    ne_free(components);}void pair_string_free(char **pairs) {    int n;    for (n = 0; pairs[n] != NULL; n+=2) {	ne_free(pairs[n]);    }    ne_free(pairs);}void ne_buffer_clear(ne_buffer *buf) {    memset(buf->data, 0, buf->length);    buf->used = 1;}  /* Grows for given size, returns 0 on success, -1 on error. */void ne_buffer_grow(ne_buffer *buf, size_t newsize) {#define NE_BUFFER_GROWTH 512    if (newsize > buf->length) {	/* If it's not big enough already... */	buf->length = ((newsize / NE_BUFFER_GROWTH) + 1) * NE_BUFFER_GROWTH;		/* Reallocate bigger buffer */	buf->data = ne_realloc(buf->data, buf->length);    }}static size_t count_concat(va_list *ap){    size_t total = 0;    char *next;    while ((next = va_arg(*ap, char *)) != NULL)	total += strlen(next);    return total;}static void do_concat(char *str, va_list *ap) {    char *next;    while ((next = va_arg(*ap, char *)) != NULL) {#ifdef HAVE_STPCPY        str = stpcpy(str, next);#else	size_t len = strlen(next);	memcpy(str, next, len);	str += len;#endif    }}void ne_buffer_concat(ne_buffer *buf, ...){    va_list ap;    ssize_t total;    va_start(ap, buf);    total = buf->used + count_concat(&ap);    va_end(ap);        /* Grow the buffer */    ne_buffer_grow(buf, total);        va_start(ap, buf);        do_concat(buf->data + buf->used - 1, &ap);    va_end(ap);        buf->used = total;    buf->data[total - 1] = '\0';}char *ne_concat(const char *str, ...){    va_list ap;    size_t total, slen = strlen(str);    char *ret;    va_start(ap, str);    total = slen + count_concat(&ap);    va_end(ap);    ret = memcpy(ne_malloc(total + 1), str, slen);    va_start(ap, str);    do_concat(ret + slen, &ap);    va_end(ap);    ret[total] = '\0';    return ret;    }/* Append zero-terminated string... returns 0 on success or -1 on * realloc failure. */void ne_buffer_zappend(ne_buffer *buf, const char *str) {    ne_buffer_append(buf, str, strlen(str));}void ne_buffer_append(ne_buffer *buf, const char *data, size_t len) {    ne_buffer_grow(buf, buf->used + len);    memcpy(buf->data + buf->used - 1, data, len);    buf->used += len;    buf->data[buf->used - 1] = '\0';}ne_buffer *ne_buffer_create(void) {    return ne_buffer_ncreate(512);}ne_buffer *ne_buffer_ncreate(size_t s) {    ne_buffer *buf = ne_malloc(sizeof(*buf));    buf->data = ne_malloc(s);    buf->data[0] = '\0';    buf->length = s;    buf->used = 1;    return buf;}void ne_buffer_destroy(ne_buffer *buf) {    ne_free(buf->data);    ne_free(buf);}char *ne_buffer_finish(ne_buffer *buf){    char *ret = buf->data;    ne_free(buf);    return ret;}void ne_buffer_altered(ne_buffer *buf){    buf->used = strlen(buf->data) + 1;}static const char *b64_alphabet =      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    "abcdefghijklmnopqrstuvwxyz"    "0123456789+/=";    char *ne_base64(const unsigned char *text, size_t inlen){    /* The tricky thing about this is doing the padding at the end,     * doing the bit manipulation requires a bit of concentration only */    char *buffer, *point;    size_t outlen;        /* Use 'buffer' to store the output. Work out how big it should be...     * This must be a multiple of 4 bytes */    outlen = (inlen*4)/3;    if ((inlen % 3) > 0) /* got to pad */	outlen += 4 - (inlen % 3);        buffer = ne_malloc(outlen + 1); /* +1 for the \0 */        /* now do the main stage of conversion, 3 bytes at a time,     * leave the trailing bytes (if there are any) for later */    for (point=buffer; inlen>=3; inlen-=3, text+=3) {	*(point++) = b64_alphabet[ (*text)>>2 ]; 	*(point++) = b64_alphabet[ ((*text)<<4 & 0x30) | (*(text+1))>>4 ]; 	*(point++) = b64_alphabet[ ((*(text+1))<<2 & 0x3c) | (*(text+2))>>6 ];	*(point++) = b64_alphabet[ (*(text+2)) & 0x3f ];    }    /* Now deal with the trailing bytes */    if (inlen > 0) {	/* We always have one trailing byte */	*(point++) = b64_alphabet[ (*text)>>2 ];	*(point++) = b64_alphabet[ (((*text)<<4 & 0x30) |				     (inlen==2?(*(text+1))>>4:0)) ]; 	*(point++) = (inlen==1?'=':b64_alphabet[ (*(text+1))<<2 & 0x3c ]);	*(point++) = '=';    }    /* Null-terminate */    *point = '\0';    return buffer;}/* VALID_B64: fail if 'ch' is not a valid base64 character */#define VALID_B64(ch) (((ch) >= 'A' && (ch) <= 'Z') || \                       ((ch) >= 'a' && (ch) <= 'z') || \                       ((ch) >= '0' && (ch) <= '9') || \                       (ch) == '/' || (ch) == '+' || (ch) == '=')/* DECODE_B64: decodes a valid base64 character. */#define DECODE_B64(ch) ((ch) >= 'a' ? ((ch) + 26 - 'a') : \                        ((ch) >= 'A' ? ((ch) - 'A') : \                         ((ch) >= '0' ? ((ch) + 52 - '0') : \                          ((ch) == '+' ? 62 : 63))))size_t ne_unbase64(const char *data, unsigned char **out){    size_t inlen = strlen(data);    unsigned char *outp;    const unsigned char *in;    if (inlen == 0 || (inlen % 4) != 0) return 0;        outp = *out = ne_malloc(inlen * 3 / 4);    for (in = (const unsigned char *)data; *in; in += 4) {        unsigned int tmp;        if (!VALID_B64(in[0]) || !VALID_B64(in[1]) || !VALID_B64(in[2]) ||            !VALID_B64(in[3]) || in[0] == '=' || in[1] == '=' ||            (in[2] == '=' && in[3] != '=')) {            ne_free(*out);            return 0;        }        tmp = (DECODE_B64(in[0]) & 0x3f) << 18 |            (DECODE_B64(in[1]) & 0x3f) << 12;        *outp++ = (tmp >> 16) & 0xff;        if (in[2] != '=') {            tmp |= (DECODE_B64(in[2]) & 0x3f) << 6;            *outp++ = (tmp >> 8) & 0xff;            if (in[3] != '=') {                tmp |= DECODE_B64(in[3]) & 0x3f;                *outp++ = tmp & 0xff;            }        }    }    return outp - *out;}char *ne_strclean(char *str){    char *pnt;    for (pnt = str; *pnt; pnt++)        if (iscntrl(*pnt) || !isprint(*pnt)) *pnt = ' ';    return str;}char *ne_strerror(int errnum, char *buf, size_t buflen){#ifdef HAVE_STRERROR_R#ifdef STRERROR_R_CHAR_P    /* glibc-style strerror_r which may-or-may-not use provided buffer. */    char *ret = strerror_r(errnum, buf, buflen);    if (ret != buf)	ne_strnzcpy(buf, ret, buflen);#else /* POSIX-style strerror_r: */    strerror_r(errnum, buf, buflen);#endif#else /* no strerror_r: */    ne_strnzcpy(buf, strerror(errnum), buflen);#endif    return buf;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -