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

📄 stringinfo.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
字号:
/*------------------------------------------------------------------------- * * stringinfo.c * * StringInfo provides an indefinitely-extensible string data type. * It can be used to buffer either ordinary C strings (null-terminated text) * or arbitrary binary data.  All storage is allocated with palloc(). * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *	  $PostgreSQL: pgsql/src/backend/lib/stringinfo.c,v 1.42 2005/10/15 02:49:17 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "lib/stringinfo.h"#include "utils/memutils.h"/* * makeStringInfo * * Create an empty 'StringInfoData' & return a pointer to it. */StringInfomakeStringInfo(void){	StringInfo	res;	res = (StringInfo) palloc(sizeof(StringInfoData));	initStringInfo(res);	return res;}/* * initStringInfo * * Initialize a StringInfoData struct (with previously undefined contents) * to describe an empty string. */voidinitStringInfo(StringInfo str){	int			size = 256;		/* initial default buffer size */	str->data = (char *) palloc(size);	str->maxlen = size;	str->len = 0;	str->data[0] = '\0';	str->cursor = 0;}/* * appendStringInfo * * Format text data under the control of fmt (an sprintf-style format string) * and append it to whatever is already in str.  More space is allocated * to str if necessary.  This is sort of like a combination of sprintf and * strcat. */voidappendStringInfo(StringInfo str, const char *fmt,...){	for (;;)	{		va_list		args;		bool		success;		/* Try to format the data. */		va_start(args, fmt);		success = appendStringInfoVA(str, fmt, args);		va_end(args);		if (success)			break;		/* Double the buffer size and try again. */		enlargeStringInfo(str, str->maxlen);	}}/* * appendStringInfoVA * * Attempt to format text data under the control of fmt (an sprintf-style * format string) and append it to whatever is already in str.	If successful * return true; if not (because there's not enough space), return false * without modifying str.  Typically the caller would enlarge str and retry * on false return --- see appendStringInfo for standard usage pattern. * * XXX This API is ugly, but there seems no alternative given the C spec's * restrictions on what can portably be done with va_list arguments: you have * to redo va_start before you can rescan the argument list, and we can't do * that from here. */boolappendStringInfoVA(StringInfo str, const char *fmt, va_list args){	int			avail,				nprinted;	Assert(str != NULL);	/*	 * If there's hardly any space, don't bother trying, just fail to make the	 * caller enlarge the buffer first.	 */	avail = str->maxlen - str->len - 1;	if (avail < 16)		return false;	/*	 * Assert check here is to catch buggy vsnprintf that overruns the	 * specified buffer length.  Solaris 7 in 64-bit mode is an example of a	 * platform with such a bug.	 */#ifdef USE_ASSERT_CHECKING	str->data[str->maxlen - 1] = '\0';#endif	nprinted = vsnprintf(str->data + str->len, avail, fmt, args);	Assert(str->data[str->maxlen - 1] == '\0');	/*	 * Note: some versions of vsnprintf return the number of chars actually	 * stored, but at least one returns -1 on failure. Be conservative about	 * believing whether the print worked.	 */	if (nprinted >= 0 && nprinted < avail - 1)	{		/* Success.  Note nprinted does not include trailing null. */		str->len += nprinted;		return true;	}	/* Restore the trailing null so that str is unmodified. */	str->data[str->len] = '\0';	return false;}/* * appendStringInfoString * * Append a null-terminated string to str. * Like appendStringInfo(str, "%s", s) but faster. */voidappendStringInfoString(StringInfo str, const char *s){	appendBinaryStringInfo(str, s, strlen(s));}/* * appendStringInfoChar * * Append a single byte to str. * Like appendStringInfo(str, "%c", ch) but much faster. */voidappendStringInfoChar(StringInfo str, char ch){	/* Make more room if needed */	if (str->len + 1 >= str->maxlen)		enlargeStringInfo(str, 1);	/* OK, append the character */	str->data[str->len] = ch;	str->len++;	str->data[str->len] = '\0';}/* * appendBinaryStringInfo * * Append arbitrary binary data to a StringInfo, allocating more space * if necessary. */voidappendBinaryStringInfo(StringInfo str, const char *data, int datalen){	Assert(str != NULL);	/* Make more room if needed */	enlargeStringInfo(str, datalen);	/* OK, append the data */	memcpy(str->data + str->len, data, datalen);	str->len += datalen;	/*	 * Keep a trailing null in place, even though it's probably useless for	 * binary data...	 */	str->data[str->len] = '\0';}/* * enlargeStringInfo * * Make sure there is enough space for 'needed' more bytes * ('needed' does not include the terminating null). * * External callers usually need not concern themselves with this, since * all stringinfo.c routines do it automatically.  However, if a caller * knows that a StringInfo will eventually become X bytes large, it * can save some palloc overhead by enlarging the buffer before starting * to store data in it. * * NB: because we use repalloc() to enlarge the buffer, the string buffer * will remain allocated in the same memory context that was current when * initStringInfo was called, even if another context is now current. * This is the desired and indeed critical behavior! */voidenlargeStringInfo(StringInfo str, int needed){	int			newlen;	/*	 * Guard against ridiculous "needed" values, which can occur if we're fed	 * bogus data.	Without this, we can get an overflow or infinite loop in	 * the following.	 */	if (needed < 0 ||		((Size) needed) >= (MaxAllocSize - (Size) str->len))		elog(ERROR, "invalid string enlargement request size %d",			 needed);	needed += str->len + 1;		/* total space required now */	/* Because of the above test, we now have needed <= MaxAllocSize */	if (needed <= str->maxlen)		return;					/* got enough space already */	/*	 * We don't want to allocate just a little more space with each append;	 * for efficiency, double the buffer size each time it overflows.	 * Actually, we might need to more than double it if 'needed' is big...	 */	newlen = 2 * str->maxlen;	while (needed > newlen)		newlen = 2 * newlen;	/*	 * Clamp to MaxAllocSize in case we went past it.  Note we are assuming	 * here that MaxAllocSize <= INT_MAX/2, else the above loop could	 * overflow.  We will still have newlen >= needed.	 */	if (newlen > (int) MaxAllocSize)		newlen = (int) MaxAllocSize;	str->data = (char *) repalloc(str->data, newlen);	str->maxlen = newlen;}

⌨️ 快捷键说明

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