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

📄 string.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * string - string list routines * * Copyright (C) 1999-2006  David I. Bell and Ernest Bowen * * Primary author:  David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc 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 Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL.  You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. * * @(#) $Revision: 29.10 $ * @(#) $Id: string.c,v 29.10 2006/08/20 15:01:30 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/string.c,v $ * * Under source code control:	1990/02/15 01:48:10 * File existed as early as:	before 1990 * * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include "calc.h"#include "string.h"#define STR_TABLECHUNK	100	/* how often to reallocate string table */#define STR_CHUNK	2000	/* size of string storage allocation */#define STR_UNIQUE	100	/* size of string to allocate separately */STRING _nullstring_ = {"", 0, 1, NULL};static char *chartable;		/* single character string table */static struct {	long l_count;		/* count of strings in table */	long l_maxcount;	/* maximum strings storable in table */	size_t l_avail;		/* characters available in current string */	char *l_alloc;		/* next available string storage */	char **l_table;		/* current string table */} literals;/* * Initialize or reinitialize a string header for use. * * given: *	hp		structure to be inited */voidinitstr(STRINGHEAD *hp){	if (hp->h_list == NULL) {		hp->h_list = (char *)malloc(2000);		hp->h_avail = 2000;		hp->h_used = 0;	}	hp->h_avail += hp->h_used;	hp->h_used = 0;	hp->h_count = 0;	hp->h_list[0] = '\0';	hp->h_list[1] = '\0';}/* * Copy a string to the end of a list of strings, and return the address * of the copied string.  Returns NULL if the string could not be copied. * No checks are made to see if the string is already in the list. * The string cannot be null or have imbedded nulls. * * given: *	hp		header of string storage *	str		string to be added */char *addstr(STRINGHEAD *hp, char *str){	char *retstr;		/* returned string pointer */	char *list;		/* string list */	long newsize;		/* new size of string list */	size_t len;		/* length of current string */	if ((str == NULL) || (*str == '\0'))		return NULL;	len = strlen(str) + 1;	if (hp->h_avail <= len) {		newsize = len + 2000 + hp->h_used + hp->h_avail;		list = (char *)realloc(hp->h_list, newsize);		if (list == NULL)			return NULL;		hp->h_list = list;		hp->h_avail = newsize - hp->h_used;	}	retstr = hp->h_list + hp->h_used;	hp->h_used += len;	hp->h_avail -= len;	hp->h_count++;	strcpy(retstr, str);	retstr[len] = '\0';	return retstr;}/* * Return a null-terminated string which consists of a single character. * The table is initialized on the first call. */char *charstr(int ch){	char *cp;	int i;	if (chartable == NULL) {		cp = (char *)malloc(512);		if (cp == NULL) {			math_error("Cannot allocate character table");			/*NOTREACHED*/		}		for (i = 0; i < 256; i++) {			*cp++ = (char)i;			*cp++ = '\0';		}		chartable = cp - 512;	}	return &chartable[(ch & 0xff) * 2];}/* * Find a string with the specified name and return its number in the * string list.	 The first string is numbered zero.  Minus one is returned * if the string is not found. * * given: *	hp		header of string storage *	str		string to be added */intfindstr(STRINGHEAD *hp, char *str){	register char *test;	/* string being tested */	size_t len;		/* length of string being found */	size_t testlen;		/* length of test string */	int index;		/* index of string */	if ((hp->h_count <= 0) || (str == NULL))		return -1;	len = strlen(str);	test = hp->h_list;	index = 0;	while (*test) {		testlen = strlen(test);		if ((testlen == len) && (*test == *str) && (strcmp(test, str) == 0))			return index;		test += (testlen + 1);		index++;	}	return -1;}/* * Return the name of a string with the given index. * If the index is illegal, a pointer to an empty string is returned. * * given: *	hp		header of string storage *	n		string index */char *namestr(STRINGHEAD *hp, long n){	register char *str;	/* current string */	if (n >= hp->h_count)		return "";	str = hp->h_list;	while (*str) {		if (--n < 0)			return str;		str += (strlen(str) + 1);	}	return "";}/* * Useful routine to return the index of one string within another one * which has the format:  "str1\000str2\000str3\000...strn\0\0".  Index starts * at one for the first string.	 Returns zero if the string being checked * is not contained in the formatted string. * * Be sure to use \000 instead of \0.  ANSI-C compilers interpret "foo\0foo..." * as "foo\017oo...". * * given: *	format		string formatted into substrings *	test		string to be found in formatted string */longstringindex(char *format, char *test){	long index;		/* found index */	size_t len;		/* length of current piece of string */	size_t testlen;		/* length of test string */	testlen = strlen(test);	index = 1;	while (*format) {		len = strlen(format);		if ((len == testlen) && (*format == *test) &&			(strcmp(format, test) == 0))				return index;		format += (len + 1);		index++;	}	return 0;}/* * Add a possibly new literal string to the literal string pool. * Returns the new string address which is guaranteed to be always valid. * Duplicate strings will repeatedly return the same address. */char *addliteral(char *str){	register char **table;	/* table of strings */	char *newstr;		/* newly allocated string */	long count;		/* number of strings */	size_t len;		/* length of string to allocate */	len = strlen(str);	if (len <= 1)		return charstr(*str);	/*	 * See if the string is already in the table.	 */	table = literals.l_table;	count = literals.l_count;	while (count-- > 0) {		if ((str[0] == table[0][0]) && (str[1] == table[0][1]) &&			(strcmp(str, table[0]) == 0))				return table[0];		table++;	}	/*	 * Make the table of string pointers larger if necessary.	 */	if (literals.l_count >= literals.l_maxcount) {		count = literals.l_maxcount + STR_TABLECHUNK;		if (literals.l_maxcount)			table = (char **) realloc(literals.l_table, count * sizeof(char *));		else			table = (char **) malloc(count * sizeof(char *));		if (table == NULL) {			math_error("Cannot allocate string literal table");			/*NOTREACHED*/		}		literals.l_table = table;		literals.l_maxcount = count;	}	table = literals.l_table;	/*	 * If the new string is very long, allocate it manually.	 */	len = (len + 2) & ~1;	/* add room for null and round up to word */	if (len >= STR_UNIQUE) {		newstr = (char *)malloc(len);		if (newstr == NULL) {			math_error("Cannot allocate large literal string");			/*NOTREACHED*/		}		strcpy(newstr, str);		table[literals.l_count++] = newstr;		return newstr;	}	/*	 * If the remaining space in the allocate string is too small,	 * then allocate a new one.	 */	if (literals.l_avail < len) {		newstr = (char *)malloc(STR_CHUNK);		if (newstr == NULL) {			math_error("Cannot allocate new literal string");			/*NOTREACHED*/		}		literals.l_alloc = newstr;		literals.l_avail = STR_CHUNK;	}	/*	 * Allocate the new string from the allocate string.	 */	newstr = literals.l_alloc;	literals.l_avail -= len;	literals.l_alloc += len;	table[literals.l_count++] = newstr;	strcpy(newstr, str);	return newstr;}STRING *stringadd(STRING *s1, STRING *s2){	STRING *s;	char *cfrom, *c;	long len;	len = s1->s_len + s2->s_len;	s = stralloc();	s->s_len = len;	s->s_str = (char *) malloc(len + 1);	if (s->s_str == NULL)		return NULL;	len = s1->s_len;	cfrom = s1->s_str;	c = s->s_str;	while (len-- > 0)		*c++ = *cfrom++;	len = s2->s_len;	cfrom = s2->s_str;	while (len-- > 0)		*c++ = *cfrom++;	*c = '\0';	return s;}/* * stringneg reverses the characters in a string, returns null if malloc fails */STRING *stringneg(STRING *str){	long len;	STRING *s;	char *c, *cfrom;	len = str->s_len;	if (len <= 1)		return slink(str);	c = (char *) malloc(len + 1);	if (c == NULL)		return NULL;	s = stralloc();	s->s_len = len;	s->s_str = c;	cfrom = str->s_str + len;	while (len-- > 0)		*c++ = *--cfrom;	*c = '\0';	return s;}STRING *stringsub(STRING *s1, STRING *s2){	STRING *tmp, *s;	tmp = stringneg(s2);	if (tmp == NULL)		return NULL;	s = stringadd(s1, tmp);	if (s != NULL)		sfree(tmp);	return s;}/* * stringmul: repeated concatenation, reverse if negative multiplier * returns null if malloc fails */STRING *stringmul(NUMBER *q, STRING *str){	long len;	size_t j;	NUMBER *tmp1, *tmp2;	char *c, *c1;	STRING *s;	BOOL neg;	if (str->s_len == 0)		return slink(str);	neg = qisneg(q);	q = neg ? qneg(q): qlink(q);	tmp1 = itoq(str->s_len);	tmp2 = qmul(q, tmp1);	qfree(tmp1);	tmp1 = qint(tmp2);	qfree(tmp2);	if (zge31b(tmp1->num)) {		qfree(q);		qfree(tmp1);		return NULL;	}	len = qtoi(tmp1);	qfree(tmp1);	qfree(q);	if (len == 0)		return slink(&_nullstring_);	c = (char *) malloc(len + 1);	if (c == NULL)		return NULL;	str = neg ? stringneg(str) : slink(str);	s = stralloc();	s->s_str = c;	s->s_len = len;	j = 0;	c1 = str->s_str;	while (len-- > 0) {		*c++ = *c1++;		if (++j == str->s_len) {			j = 0;			c1 = str->s_str;		}	}	*c = '\0';	sfree(str);	return s;}STRING *stringand(STRING *s1, STRING *s2){	STRING *s;	size_t len;	char *c1, *c2, *c;	if (s1->s_len == 0  || s2->s_len == 0)		return slink(&_nullstring_);	len = s1->s_len;	if (s2->s_len < len)		len = s2->s_len;	s = stralloc();	s->s_len = len;	c = malloc(len + 1);	if (c == NULL)		return NULL;	s->s_str = c;	c1 = s1->s_str;	c2 = s2->s_str;	while (len-- > 0)		*c++ = *c1++ & *c2++;	return s;}STRING *stringor(STRING *s1, STRING *s2){	STRING *s;	long len, i, j;	char *c1, *c2, *c;	if (s1->s_len < s2->s_len) {		s = s1;		s1 = s2;		s2 = s;	}		/* Now len(s1) >= len(s2) */	if (s2->s_len == 0)		return slink(s1);	i = s1->s_len;	if (i == 0)		return slink(&_nullstring_);	len = s1->s_len;	s = stralloc();	s->s_len = len;	c = malloc(len + 1);	if (c == NULL)		return NULL;	s->s_str = c;	c1 = s1->s_str;	c2 = s2->s_str;	i = s2->s_len;	j = s1->s_len - i;	while (i-- > 0)		*c++ = *c1++ | *c2++;	while (j-- > 0)		*c++ = *c1++;	return s;}STRING *stringxor(STRING *s1, STRING *s2){	STRING *s;	long len, i, j;	char *c1, *c2, *c;	if (s1->s_len < s2->s_len) {		s = s1;		s1 = s2;		s2 = s;	}		/* Now len(s1) >= len(s2) */	if (s2->s_len == 0)		return slink(s1);	i = s1->s_len;	if (i == 0)		return slink(&_nullstring_);	len = s1->s_len;	s = stralloc();	s->s_len = len;	c = malloc(len + 1);	if (c == NULL)		return NULL;	s->s_str = c;	c1 = s1->s_str;	c2 = s2->s_str;	i = s2->s_len;	j = s1->s_len - i;	while (i-- > 0)		*c++ = *c1++ ^ *c2++;	while (j-- > 0)		*c++ = *c1++;	return s;}STRING *stringdiff(STRING *s1, STRING *s2){	STRING *s;	size_t i;	char *c2, *c;	i = s1->s_len;	if (i == 0)		return slink(s1);	s = stringcopy(s1);	if (i > s2->s_len)		i = s2->s_len;	c = s->s_str;	c2 = s2->s_str;	while (i-- > 0)		*c++ &= ~*c2++;	return s;}STRING *stringcomp(STRING *s1){	long len;	STRING *s;	char *c1, *c;	len = s1->s_len;	if (len == 0)		return slink(&_nullstring_);	c = malloc(len + 1);	if (c == NULL)		return NULL;	s = stralloc();	s->s_len = len;	s->s_str = c;	c1 = s1->s_str;	while (len-- > 0)		*c++ = ~*c1++;	*c = '\0';	return s;}STRING *stringsegment(STRING *s1, long n1, long n2){	STRING *s;	char *c, *c1;	long len;	if ((n1 < 0 && n2 < 0) ||	    ((size_t)n1 >= s1->s_len && (size_t)n2 >= s1->s_len))		return slink(&_nullstring_);	if (n1 < 0)		n1 = 0;	if (n2 < 0)		n2 = 0;	if ((size_t)n1 >= s1->s_len)		n1 = s1->s_len - 1;	if ((size_t)n2 >= s1->s_len)		n2 = s1->s_len - 1;	len = (n1 >= n2) ? n1 - n2 + 1 : n2 - n1 + 1;	s = stralloc();	c = malloc(len + 1);	if (c == NULL)		return NULL;	s->s_len = len;	s->s_str = c;	c1 = s1->s_str + n1;	if (n1 >= n2) {		/*		 * We prevent the c1 pointer from walking behind s1_s_str		 * by stopping one short of the end and running the loop one		 * more time.		 *		 * We could stop the loop with just len-- > 0, but stopping		 * short and running the loop one last time manually helps make		 * code checkers such as insure happy.		 */		while (len-- > 1) {			*c++ = *c1--;		}		/* run the loop manually one last time */		*c++ = *c1;	} else {		while (len-- > 0)			*c++ = *c1++;	}	*c = '\0';	return s;}/* * stringshift shifts s1 n bits to left if n > 0, -n to the right if n < 0; * octets in string considered to be in decreasing order of index, as in * ... a_3 a_2 a_1 a_0.	 Returned string has same length as s1. * Vacated bits are filled with '\0'; bits shifted off end are lost */STRING *stringshift(STRING *s1, long n){	char *c1, *c;	STRING *s;	long len, i, j, k;	BOOL right;	char ch;	len = s1->s_len;	if (len == 0 || n == 0)		return slink(s1);	right = (n < 0);	if (right) n = -n;	j = n & 7;	k = 8 - j;	n >>= 3;	c = malloc(len + 1);	if (c == NULL)		return NULL;	s = stralloc();	s->s_len = len;	s->s_str = c;	c[len] = '\0';	if (n > len)		n = len;	ch = '\0';	c1 = s1->s_str;	i = n;	if (right) {		c += len;		c1 += len;		while (i-- > 0)			*--c = '\0';		i = len - n;		while (i-- > 0) {			*--c = ((unsigned char) *--c1 >> j) | ch;			ch = (unsigned char) *c1 << k;		}	} else {		while (i-- > 0)			*c++ = '\0';		i = len - n;		while (i-- > 0) {			*c++ = ((unsigned char) *c1 << j) | ch;			ch = (unsigned char) *c1++ >> k;		}	}	return s;}/* * stringcpy copies as many characters as possible * from s2 to s1 and returns s1 */STRING *stringcpy(STRING *s1, STRING *s2){	char *c1, *c2;	size_t num;	if (s1->s_len > 0) {		c1 = s1->s_str;		c2 = s2->s_str;		num = s1->s_len;		if (num > s2->s_len)			num = s2->s_len;		while (num-- > 0)			*c1++ = *c2++;		*c1 = '\0';	}	return slink(s1);}/* * stringncpy copies up to num characters from s2 to s1 and returns s1 * If num > size(s2) null characters are copied until s1 is full or * a total of num characters have been copied */STRING *stringncpy(STRING *s1, STRING *s2, size_t num){	char *c1, *c2;	size_t i;	if (num > s1->s_len)		num = s1->s_len;	i = num;	if (i > s2->s_len)		i = s2->s_len;	c1 = s1->s_str;

⌨️ 快捷键说明

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