1 /* data-mem.c - A memory based data object.
2 Copyright (C) 2002 g10 Code GmbH
4 This file is part of GPGME.
6 GPGME is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 GPGME is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GPGME; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
34 mem_read (GpgmeData dh, void *buffer, size_t size)
36 size_t amt = dh->data.mem.length - dh->data.mem.offset;
45 src = dh->data.mem.buffer ? dh->data.mem.buffer : dh->data.mem.orig_buffer;
46 memcpy (buffer, src + dh->data.mem.offset, amt);
47 dh->data.mem.offset += amt;
53 mem_write (GpgmeData dh, const void *buffer, size_t size)
57 if (!dh->data.mem.buffer && dh->data.mem.orig_buffer)
59 size_t new_size = dh->data.mem.size;
62 if (new_size < dh->data.mem.offset + size)
63 new_size = dh->data.mem.offset + size;
65 new_buffer = malloc (new_size);
68 dh->data.mem.buffer = new_buffer;
69 dh->data.mem.size = new_size;
72 unused = dh->data.mem.size - dh->data.mem.offset;
75 /* Allocate a large enough buffer with exponential backoff. */
76 #define INITIAL_ALLOC 512
77 size_t new_size = dh->data.mem.size
78 ? (2 * dh->data.mem.size) : INITIAL_ALLOC;
81 if (new_size < dh->data.mem.offset + size)
82 new_size = dh->data.mem.offset + size;
84 new_buffer = realloc (dh->data.mem.buffer, new_size);
85 if (!new_buffer && new_size > dh->data.mem.offset + size)
87 /* Maybe we were too greedy, try again. */
88 new_size = dh->data.mem.offset + size;
89 new_buffer = realloc (dh->data.mem.buffer, new_size);
93 dh->data.mem.buffer = new_buffer;
94 dh->data.mem.size = new_size;
97 memcpy (dh->data.mem.buffer + dh->data.mem.offset, buffer, size);
98 dh->data.mem.offset += size;
99 if (dh->data.mem.length < dh->data.mem.offset)
100 dh->data.mem.length = dh->data.mem.offset;
106 mem_seek (GpgmeData dh, off_t offset, int whence)
111 if (offset < 0 || offset > dh->data.mem.length)
116 dh->data.mem.offset = offset;
119 if ((offset > 0 && dh->data.mem.length - dh->data.mem.offset < offset)
120 || (offset < 0 && dh->data.mem.offset < -offset))
125 dh->data.mem.offset += offset;
128 if (offset > 0 || -offset > dh->data.mem.length)
133 dh->data.mem.offset = dh->data.mem.length - offset;
139 return dh->data.mem.offset;
144 mem_release (GpgmeData dh)
146 if (dh->data.mem.buffer)
147 free (dh->data.mem.buffer);
151 static struct gpgme_data_cbs mem_cbs =
161 gpgme_data_new (GpgmeData *dh)
163 GpgmeError err = _gpgme_data_new (dh, &mem_cbs);
171 /* Create a new data buffer filled with SIZE bytes starting from
172 BUFFER. If COPY is zero, copying is delayed until necessary, and
173 the data is taken from the original location when needed. */
175 gpgme_data_new_from_mem (GpgmeData *dh, const char *buffer,
176 size_t size, int copy)
178 GpgmeError err = _gpgme_data_new (dh, &mem_cbs);
184 char *bufcpy = malloc (size);
186 _gpgme_data_release (*dh);
187 memcpy (bufcpy, buffer, size);
188 (*dh)->data.mem.buffer = bufcpy;
191 (*dh)->data.mem.orig_buffer = buffer;
193 (*dh)->data.mem.size = size;
194 (*dh)->data.mem.length = size;
199 /* This function does make sense when we know that it contains no nil
200 chars and if the underlying data object is memory based. */
202 _gpgme_data_get_as_string (GpgmeData dh)
205 const char *src = NULL;
207 assert (dh->cbs == &mem_cbs);
209 src = dh->data.mem.buffer;
211 src = dh->data.mem.orig_buffer;
212 dst = malloc (dh->data.mem.length + 1);
216 memcpy (dst, src, dh->data.mem.length);
217 dst[dh->data.mem.length] = '\0';
224 gpgme_data_release_and_get_mem (GpgmeData dh, size_t *r_len)
228 if (!dh || dh->cbs != &mem_cbs)
231 str = dh->data.mem.buffer;
232 if (!str && dh->data.mem.orig_buffer)
234 str = malloc (dh->data.mem.length);
237 memcpy (str, dh->data.mem.orig_buffer, dh->data.mem.length);
241 *r_len = dh->data.mem.length;
247 /* This function does make sense when we know that it contains no nil
248 chars and if the underlying data object is memory based. */
250 _gpgme_data_release_and_return_string (GpgmeData dh)
257 assert (dh->cbs == &mem_cbs);
258 if (gpgme_data_write (dh, "", 1) == 1)
259 str = gpgme_data_release_and_get_mem (dh, NULL);
261 gpgme_data_release (dh);