enhanced resizing of qse_lda_t and qse_str_t
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: lda.c 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * $Id: lda.c 360 2010-10-21 13:29:12Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -347,12 +347,14 @@ size_t qse_lda_insert (lda_t* lda, size_t pos, void* dptr, size_t dlen) | ||||
| 	 * doesn't modify lda on any errors */ | ||||
| 	if (pos >= lda->capa || lda->size >= lda->capa)  | ||||
| 	{ | ||||
| 		size_t capa; | ||||
| 		size_t capa, mincapa; | ||||
|  | ||||
| 		/* get the minimum capacity needed */ | ||||
| 		mincapa = (pos >= lda->size)? (pos + 1): (lda->size + 1); | ||||
|  | ||||
| 		if (lda->sizer) | ||||
| 		{ | ||||
| 			capa = (pos >= lda->size)? (pos + 1): (lda->size + 1); | ||||
| 			capa = lda->sizer (lda, capa); | ||||
| 			capa = lda->sizer (lda, mincapa); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @ -368,13 +370,21 @@ size_t qse_lda_insert (lda_t* lda, size_t pos, void* dptr, size_t dlen) | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		if (qse_lda_setcapa(lda,capa) == QSE_NULL)  | ||||
| 		do | ||||
| 		{ | ||||
| 			if (lda->freeer)  | ||||
| 				lda->freeer (lda, DPTR(node), DLEN(node)); | ||||
| 			QSE_MMGR_FREE (lda->mmgr, node); | ||||
| 			return QSE_LDA_NIL; | ||||
| 		} | ||||
| 			if (qse_lda_setcapa(lda,capa) != QSE_NULL) break; | ||||
|  | ||||
| 			if (capa <= mincapa) | ||||
| 			{ | ||||
| 				if (lda->freeer)  | ||||
| 					lda->freeer (lda, DPTR(node), DLEN(node)); | ||||
| 				QSE_MMGR_FREE (lda->mmgr, node); | ||||
| 				return QSE_LDA_NIL; | ||||
| 			} | ||||
|  | ||||
| 			capa--; /* let it retry after lowering the capacity */ | ||||
| 		}  | ||||
| 		while (1); | ||||
| 	} | ||||
|  | ||||
| 	if (pos >= lda->capa || lda->size >= lda->capa)  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: str_dyn.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ | ||||
|  * $Id: str_dyn.c 360 2010-10-21 13:29:12Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -256,12 +256,16 @@ qse_size_t qse_str_ncat (qse_str_t* str, const qse_char_t* s, qse_size_t len) | ||||
| { | ||||
| 	if (len > str->capa - str->len)  | ||||
| 	{ | ||||
| 		qse_size_t ncapa; | ||||
| 		qse_size_t ncapa, mincapa; | ||||
|  | ||||
| 		/* let the minimum capacity be as large as  | ||||
| 		 * to fit in the new substring */ | ||||
| 		mincapa = str->len + len; | ||||
|  | ||||
| 		if (str->sizer == QSE_NULL) | ||||
| 		{ | ||||
| 			/* increase the capacity by the length to add */ | ||||
| 			ncapa = str->len + len; | ||||
| 			ncapa = mincapa; | ||||
| 			/* if the new capacity is less than the double, | ||||
| 			 * just double it */ | ||||
| 			if (ncapa < str->capa * 2) ncapa = str->capa * 2; | ||||
| @ -270,15 +274,19 @@ qse_size_t qse_str_ncat (qse_str_t* str, const qse_char_t* s, qse_size_t len) | ||||
| 		{ | ||||
| 			/* let the user determine the new capacity. | ||||
| 			 * pass the minimum capacity required as a hint */ | ||||
| 			ncapa = str->sizer (str, str->len + len); | ||||
| 			ncapa = str->sizer (str, mincapa); | ||||
| 			/* if no change in capacity, return current length */ | ||||
| 			if (ncapa == str->capa) return str->len; | ||||
| 		} | ||||
|  | ||||
| 		if (qse_str_setcapa (str, ncapa) == (qse_size_t)-1)  | ||||
| 		/* change the capacity */ | ||||
| 		do | ||||
| 		{ | ||||
| 			return (qse_size_t)-1; | ||||
| 			if (qse_str_setcapa (str, ncapa) != (qse_size_t)-1) break; | ||||
| 			if (ncapa <= mincapa) return (qse_size_t)-1; | ||||
| 			ncapa--; | ||||
| 		} | ||||
| 		while (1); | ||||
| 	} | ||||
|  | ||||
| 	if (len > str->capa - str->len)  | ||||
|  | ||||
| @ -705,24 +705,39 @@ void qse_xma_free (qse_xma_t* xma, void* b) | ||||
| void qse_xma_dump (qse_xma_t* xma,  qse_xma_dumper_t dumper, void* target) | ||||
| { | ||||
| 	qse_xma_blk_t* tmp; | ||||
| 	unsigned long long fsum, asum;  | ||||
| 	qse_ulong_t fsum, asum;  | ||||
| #ifdef QSE_XMA_ENABLE_STAT | ||||
| 	unsigned long long isum; | ||||
| 	qse_ulong_t isum; | ||||
| #endif | ||||
|  | ||||
| 	dumper (target, QSE_T("<XMA DUMP>\n")); | ||||
|  | ||||
| #ifdef QSE_XMA_ENABLE_STAT | ||||
| 	dumper (target, QSE_T("== statistics ==\n")); | ||||
| #if QSE_SIZEOF_LONG >= QSE_SIZEOF_LONG_LONG | ||||
| 	dumper (target, QSE_T("total = %lu\n"), (unsigned long)xma->stat.total); | ||||
| 	dumper (target, QSE_T("alloc = %lu\n"), (unsigned long)xma->stat.alloc); | ||||
| 	dumper (target, QSE_T("avail = %lu\n"), (unsigned long)xma->stat.avail); | ||||
| #else | ||||
| 	dumper (target, QSE_T("total = %llu\n"), (unsigned long long)xma->stat.total); | ||||
| 	dumper (target, QSE_T("alloc = %llu\n"), (unsigned long long)xma->stat.alloc); | ||||
| 	dumper (target, QSE_T("avail = %llu\n"), (unsigned long long)xma->stat.avail); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| 	dumper (target, QSE_T("== blocks ==\n")); | ||||
| 	dumper (target, QSE_T(" size               avail address\n")); | ||||
| 	for (tmp = xma->head, fsum = 0, asum = 0; tmp; tmp = tmp->b.next) | ||||
| 	{ | ||||
| 		dumper (target, QSE_T(" %-18llu %-5d %p\n"), (unsigned long long)tmp->size, tmp->avail, tmp); | ||||
| #if QSE_SIZEOF_LONG >= QSE_SIZEOF_LONG_LONG | ||||
| 		dumper (target, QSE_T(" %-18lu %-5d %p\n"),  | ||||
| 			(unsigned long)tmp->size, tmp->avail, tmp | ||||
| 		); | ||||
| #else | ||||
| 		dumper (target, QSE_T(" %-18llu %-5d %p\n"),  | ||||
| 			(unsigned long long)tmp->size, tmp->avail, tmp | ||||
| 		); | ||||
| #endif | ||||
| 		if (tmp->avail) fsum += tmp->size; | ||||
| 		else asum += tmp->size; | ||||
| 	} | ||||
| @ -732,11 +747,22 @@ void qse_xma_dump (qse_xma_t* xma,  qse_xma_dumper_t dumper, void* target) | ||||
| #endif | ||||
|  | ||||
| 	dumper (target, QSE_T("---------------------------------------\n")); | ||||
| 	dumper (target, QSE_T("Allocated blocks: %18llu bytes\n"), asum); | ||||
| 	dumper (target, QSE_T("Available blocks: %18llu bytes\n"), fsum); | ||||
| #if QSE_SIZEOF_LONG >= QSE_SIZEOF_LONG_LONG | ||||
| 	dumper (target, QSE_T("Allocated blocks: %18lu bytes\n"), (unsigned long)asum); | ||||
| 	dumper (target, QSE_T("Available blocks: %18lu bytes\n"), (unsigned long)fsum); | ||||
| #else | ||||
| 	dumper (target, QSE_T("Allocated blocks: %18llu bytes\n"), (unsigned long long)asum); | ||||
| 	dumper (target, QSE_T("Available blocks: %18llu bytes\n"), (unsigned long long)fsum); | ||||
| #endif | ||||
|  | ||||
| #ifdef QSE_XMA_ENABLE_STAT | ||||
| 	dumper (target, QSE_T("Internal use    : %18llu bytes\n"), isum); | ||||
| 	dumper (target, QSE_T("Total           : %18llu bytes\n"), asum + fsum + isum); | ||||
| #if QSE_SIZEOF_LONG >= QSE_SIZEOF_LONG_LONG | ||||
| 	dumper (target, QSE_T("Internal use    : %18lu bytes\n"), (unsigned long)isum); | ||||
| 	dumper (target, QSE_T("Total           : %18lu bytes\n"), (unsigned long)(asum + fsum + isum)); | ||||
| #else | ||||
| 	dumper (target, QSE_T("Internal use    : %18llu bytes\n"), (unsigned long long)isum); | ||||
| 	dumper (target, QSE_T("Total           : %18llu bytes\n"), (unsigned long long)(asum + fsum + isum)); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| 	QSE_ASSERT (asum == xma->stat.alloc); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sed.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ | ||||
|  * $Id: sed.c 360 2010-10-21 13:29:12Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -41,7 +41,7 @@ do { \ | ||||
| 	qse_sed_seterror (sed, num, &__ea__, loc); \ | ||||
| } while (0) | ||||
|  | ||||
| qse_sed_t* qse_sed_open (qse_mmgr_t* mmgr, qse_size_t xtn) | ||||
| qse_sed_t* qse_sed_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||
| { | ||||
| 	qse_sed_t* sed; | ||||
|  | ||||
| @ -55,7 +55,7 @@ qse_sed_t* qse_sed_open (qse_mmgr_t* mmgr, qse_size_t xtn) | ||||
| 		if (mmgr == QSE_NULL) return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	sed = (qse_sed_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_sed_t) + xtn); | ||||
| 	sed = (qse_sed_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_sed_t) + xtnsize); | ||||
| 	if (sed == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	if (qse_sed_init (sed, mmgr) == QSE_NULL) | ||||
|  | ||||
| @ -22,6 +22,8 @@ | ||||
| #include <qse/cmn/chr.h> | ||||
| #include "../cmn/mem.h" | ||||
|  | ||||
| QSE_IMPLEMENT_COMMON_FUNCTIONS (http) | ||||
|  | ||||
| static int is_http_space (qse_char_t c) | ||||
| { | ||||
| 	return QSE_ISSPACE(c) && c != QSE_T('\r') && c != QSE_T('\n'); | ||||
| @ -205,3 +207,165 @@ ok: | ||||
| 	*last = QSE_T('\0'); | ||||
| 	return p; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE void init_buffer (qse_http_t* http, qse_http_buf_t* buf) | ||||
| { | ||||
| 	buf->size = 0; | ||||
| 	buf->capa = 0; | ||||
| 	buf->data = QSE_NULL; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE void fini_buffer (qse_http_t* http, qse_http_buf_t* buf) | ||||
| { | ||||
| 	if (buf->data)  | ||||
| 	{ | ||||
| 		QSE_MMGR_FREE (http->mmgr, buf->data); | ||||
| 		buf->capa = 0; | ||||
| 		buf->size = 0; | ||||
| 		buf->data = QSE_NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static QSE_INLINE_ALWAYS void clear_buffer (qse_http_t* http, qse_http_buf_t* buf) | ||||
| { | ||||
| 	buf->size = 0; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int push_to_buffer ( | ||||
| 	qse_http_t* http, qse_http_buf_t* buf,  | ||||
| 	const qse_char_t* ptr, qse_size_t len) | ||||
| { | ||||
| 	qse_size_t nsize = (buf)->size + len;  | ||||
| 	const qse_char_t* end = ptr + len; | ||||
|  | ||||
| 	if (nsize > (buf)->capa)  | ||||
| 	{  | ||||
| 		qse_size_t ncapa = (nsize > (buf)->capa * 2)? nsize: ((buf)->capa * 2); | ||||
| 		 | ||||
| 		do | ||||
| 		{ | ||||
| 			void* tmp = QSE_MMGR_REALLOC ((http)->mmgr, (buf)->data, ncapa * QSE_SIZEOF(*ptr)); | ||||
| 			if (tmp) | ||||
| 			{ | ||||
| 				(buf)->capa = ncapa; | ||||
| 				(buf)->data = tmp; | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (ncapa <= nsize) | ||||
| 			{ | ||||
| 				(http)->errnum = QSE_HTTP_ENOMEM; | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			/* retry with a smaller size */ | ||||
| 			ncapa--; | ||||
| 		} | ||||
| 		while (1); | ||||
| 	} | ||||
|  | ||||
| 	while (ptr < end) (buf)->data[(buf)->size++] = *ptr++; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #define QSE_HTTP_STATE_REQ  1 | ||||
| #define QSE_HTTP_STATE_HDR  2 | ||||
| #define QSE_HTTP_STATE_POST 3 | ||||
|  | ||||
| qse_http_t* qse_http_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||
| { | ||||
| 	qse_http_t* http; | ||||
|  | ||||
| 	if (mmgr == QSE_NULL)  | ||||
| 	{ | ||||
| 		mmgr = QSE_MMGR_GETDFL(); | ||||
|  | ||||
| 		QSE_ASSERTX (mmgr != QSE_NULL, | ||||
| 			"Set the memory manager with QSE_MMGR_SETDFL()"); | ||||
|  | ||||
| 		if (mmgr == QSE_NULL) return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	http = (qse_http_t*) QSE_MMGR_ALLOC ( | ||||
| 		mmgr, QSE_SIZEOF(qse_http_t) + xtnsize | ||||
| 	); | ||||
| 	if (http == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	if (qse_http_init (http, mmgr) == QSE_NULL) | ||||
| 	{ | ||||
| 		QSE_MMGR_FREE (http->mmgr, http); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return http; | ||||
| } | ||||
|  | ||||
| void qse_http_close (qse_http_t* http) | ||||
| { | ||||
| 	qse_http_fini (http); | ||||
| 	QSE_MMGR_FREE (http->mmgr, http); | ||||
| } | ||||
|  | ||||
| qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); | ||||
|  | ||||
| 	QSE_MEMSET (http, 0, QSE_SIZEOF(*http)); | ||||
| 	http->mmgr = mmgr; | ||||
|  | ||||
| 	init_buffer (http, &http->state.buf); | ||||
| 	http->state.no = QSE_HTTP_STATE_REQ; | ||||
| 	return http; | ||||
| } | ||||
|  | ||||
| void qse_http_fini (qse_http_t* http) | ||||
| { | ||||
| 	fini_buffer (http, &http->state.buf); | ||||
| } | ||||
|  | ||||
| /* feed the percent encoded string */ | ||||
| int qse_http_feed (qse_http_t* http, const qse_char_t* ptr, qse_size_t len) | ||||
| { | ||||
| 	const qse_char_t* end = ptr + len; | ||||
| 	const qse_char_t* blk = ptr; | ||||
|  | ||||
| 	while (ptr < end) | ||||
| 	{ | ||||
| 		if (*ptr++ == '\n') | ||||
| 		{ | ||||
| 			if (push_to_buffer (http, &http->state.buf, blk, ptr - blk) <= -1) return -1; | ||||
|  | ||||
| 			blk = ptr; /* let ptr point to the next character to '\n' */ | ||||
|  | ||||
| 			if (http->state.no == QSE_HTTP_STATE_REQ) | ||||
| 			{ | ||||
| 				/* | ||||
| 				if (parse_http_req (http, &http->state.buf) <= -1) | ||||
| 				{ | ||||
| 					return -1; | ||||
| 				} | ||||
| 				*/ | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				/* | ||||
| 				if (parse_http_hdr (http, &http->state.buf) <= -1) | ||||
| 				{ | ||||
| 					return -1; | ||||
| 				} | ||||
| 				*/ | ||||
| 			} | ||||
|  | ||||
| qse_printf (QSE_T("[%.*s]\n"), (int)http->state.buf.size, http->state.buf.data); | ||||
| 			clear_buffer (http, &http->state.buf); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/* enbuffer the unfinished data */ | ||||
| 	if (push_to_buffer (http, &http->state.buf, blk, ptr - blk) <= -1) return -1; | ||||
| qse_printf (QSE_T("UNFINISHED [%.*s]\n"), (int)http->state.buf.size, http->state.buf.data); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user