1/*-------------------------------------------------------------------------
2 * drawElements Memory Pool Library
3 * --------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Memory pool management.
22 *//*--------------------------------------------------------------------*/
23
24#include "dePoolStringBuilder.h"
25
26#include <string.h>
27#include <stdarg.h>
28#include <stdio.h>
29
30typedef struct StringBlock_s
31{
32	const char*				str;
33	struct StringBlock_s*	next;
34} StringBlock;
35
36struct dePoolStringBuilder_s
37{
38	deMemPool*		pool;
39	int				length;
40	StringBlock*	blockListHead;
41	StringBlock*	blockListTail;
42};
43
44dePoolStringBuilder* dePoolStringBuilder_create (deMemPool* pool)
45{
46	dePoolStringBuilder* builder = DE_POOL_NEW(pool, dePoolStringBuilder);
47	if (!builder)
48		return DE_NULL;
49
50	builder->pool			= pool;
51	builder->length			= 0;
52	builder->blockListHead	= DE_NULL;
53	builder->blockListTail	= DE_NULL;
54
55	return builder;
56}
57
58deBool dePoolStringBuilder_appendString (dePoolStringBuilder* builder, const char* str)
59{
60	StringBlock*	block		= DE_POOL_NEW(builder->pool, StringBlock);
61	int				len			= (int)strlen(str);
62	char*			blockStr	= (char*)deMemPool_alloc(builder->pool, len + 1);
63
64	if (!block || !blockStr)
65		return DE_FALSE;
66
67	/* Initialize block. */
68	{
69		char*		d	= blockStr;
70		const char*	s	= str;
71		while (*s)
72			*d++ = *s++;
73		*d = 0;
74
75		block->str	= blockStr;
76		block->next	= DE_NULL;
77	}
78
79	/* Add block to list. */
80	if (builder->blockListTail)
81		builder->blockListTail->next = block;
82	else
83		builder->blockListHead = block;
84
85	builder->blockListTail = block;
86
87	builder->length += len;
88
89	return DE_TRUE;
90}
91
92deBool dePoolStringBuilder_appendFormat (dePoolStringBuilder* builder, const char* format, ...)
93{
94	char	buf[512];
95	va_list	args;
96	deBool	ok;
97
98	va_start(args, format);
99	vsnprintf(buf, DE_LENGTH_OF_ARRAY(buf), format, args);
100	ok = dePoolStringBuilder_appendString(builder, buf);
101	va_end(args);
102
103	return ok;
104}
105
106/* \todo [2009-09-05 petri] Other appends? printf style? */
107
108int dePoolStringBuilder_getLength (dePoolStringBuilder* builder)
109{
110	return builder->length;
111}
112
113char* dePoolStringBuilder_dupToString (dePoolStringBuilder* builder)
114{
115	return dePoolStringBuilder_dupToPool(builder, builder->pool);
116}
117
118char* dePoolStringBuilder_dupToPool (dePoolStringBuilder* builder, deMemPool* pool)
119{
120	char* resultStr = (char*)deMemPool_alloc(pool, builder->length + 1);
121
122	if (resultStr)
123	{
124		StringBlock*	block	= builder->blockListHead;
125		char*			dstPtr	= resultStr;
126
127		while (block)
128		{
129			const char* p = block->str;
130			while (*p)
131				*dstPtr++ = *p++;
132			block = block->next;
133		}
134
135		*dstPtr++ = 0;
136
137		DE_ASSERT((int)strlen(resultStr) == builder->length);
138	}
139
140	return resultStr;
141}
142