pupnp (libupnp) snapshot from SourceForge: git clone git://pupnp.git.sourceforge...
[igd2-for-linux:pandonghui1211s-igd2-for-linux.git] / pupnp_branch-1.6.x / ixml / src / ixmlmembuf.c
1 /**************************************************************************
2  *
3  * Copyright (c) 2000-2003 Intel Corporation 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions are met: 
8  *
9  * - Redistributions of source code must retain the above copyright notice, 
10  * this list of conditions and the following disclaimer. 
11  * - Redistributions in binary form must reproduce the above copyright notice, 
12  * this list of conditions and the following disclaimer in the documentation 
13  * and/or other materials provided with the distribution. 
14  * - Neither name of Intel Corporation nor the names of its contributors 
15  * may be used to endorse or promote products derived from this software 
16  * without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  **************************************************************************/
31
32
33 /*!
34  * \file
35  */
36
37
38 #include "ixmlmembuf.h"
39 #include "ixml.h"
40
41
42 #include <assert.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46
47 /*!
48  * \brief Increases or decreases buffer capacity so that at least 'new_length'
49  * bytes can be stored.
50  *
51  * On error, m's fields do not change.
52  *
53  * \return
54  *      \li UPNP_E_SUCCESS
55  *      \li UPNP_E_OUTOF_MEMORY
56  */
57 static int ixml_membuf_set_size(
58         /*! [in,out] The memory buffer. */
59         INOUT ixml_membuf *m,
60         /*! [in] The new lenght. */
61         IN size_t new_length)
62 {
63         size_t diff;
64         size_t alloc_len;
65         char *temp_buf;
66
67         if (new_length >= m->length) {
68                 /* increase length */
69                 /* need more mem? */
70                 if (new_length <= m->capacity) {
71                         /* have enough mem; done */
72                         return 0;
73                 }
74
75                 diff = new_length - m->length;
76                 alloc_len = MAXVAL(m->size_inc, diff) + m->capacity;
77         } else {
78                 // decrease length
79                 assert(new_length <= m->length);
80
81                 // if diff is 0..m->size_inc, don't free
82                 if ((m->capacity - new_length) <= m->size_inc) {
83                         return 0;
84                 }
85                 alloc_len = new_length + m->size_inc;
86         }
87
88         assert(alloc_len >= new_length);
89
90         temp_buf = realloc(m->buf, alloc_len + 1);
91         if (temp_buf == NULL) {
92                 /* try smaller size */
93                 alloc_len = new_length;
94                 temp_buf = realloc(m->buf, alloc_len + 1);
95                 if (temp_buf == NULL) {
96                         return IXML_INSUFFICIENT_MEMORY;
97                 }
98         }
99         /* save */
100         m->buf = temp_buf;
101         m->capacity = alloc_len;
102
103         return 0;
104 }
105
106
107 void ixml_membuf_init(ixml_membuf *m)
108 {
109         assert(m != NULL);
110
111         m->size_inc = MEMBUF_DEF_SIZE_INC;
112         m->buf = NULL;
113         m->length = 0;
114         m->capacity = 0;
115 }
116
117
118 void ixml_membuf_destroy(ixml_membuf *m)
119 {
120         if (m == NULL) {
121                 return;
122         }
123
124         free(m->buf);
125         ixml_membuf_init(m);
126 }
127
128
129 int ixml_membuf_assign(
130         ixml_membuf *m,
131         const void *buf,
132         size_t buf_len)
133 {
134         int return_code;
135
136         assert(m != NULL);
137
138         // set value to null
139         if (buf == NULL) {
140                 ixml_membuf_destroy(m);
141                 return IXML_SUCCESS;
142         }
143         // alloc mem
144         return_code = ixml_membuf_set_size(m, buf_len);
145         if (return_code != 0) {
146                 return return_code;
147         }
148
149         // copy
150         memcpy(m->buf, buf, buf_len);
151
152         // null-terminate
153         m->buf[buf_len] = 0;
154         m->length = buf_len;
155
156         return IXML_SUCCESS;
157 }
158
159
160 int ixml_membuf_assign_str(
161         ixml_membuf *m,
162         const char *c_str)
163 {
164         return ixml_membuf_assign(m, c_str, strlen(c_str));
165 }
166
167
168 int ixml_membuf_append(
169         INOUT ixml_membuf *m,
170         IN const void *buf)
171 {
172         assert(m != NULL);
173
174         return ixml_membuf_insert(m, buf, 1, m->length);
175 }
176
177
178 int ixml_membuf_append_str(
179         INOUT ixml_membuf *m,
180         IN const char *c_str)
181 {
182         return ixml_membuf_insert(m, c_str, strlen(c_str), m->length);
183 }
184
185
186 int ixml_membuf_insert(
187         INOUT ixml_membuf *m,
188         IN const void *buf,
189         IN size_t buf_len,
190         int index)
191 {
192         int return_code = 0;
193
194         assert(m != NULL);
195
196         if (index < 0 || index > (int)m->length) {
197                 return IXML_INDEX_SIZE_ERR;
198         }
199
200         if (buf == NULL || buf_len == 0) {
201                 return 0;
202         }
203         /* alloc mem */
204         return_code = ixml_membuf_set_size(m, m->length + buf_len);
205         if (return_code != 0) {
206                 return return_code;
207         }
208         /* insert data */
209         /* move data to right of insertion point */
210         memmove(m->buf + index + buf_len, m->buf + index, m->length - index);
211         memcpy(m->buf + index, buf, buf_len);
212         m->length += buf_len;
213         /* Null terminate */
214         m->buf[m->length] = 0;
215
216         return 0;
217 }
218