Reanmed public functions
[gpgme.git] / gpgme / data.c
1 /* data.c
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify
7  * it 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.
10  *
11  * GPGME is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <assert.h>
25
26 #include "util.h"
27 #include "context.h"
28
29
30 #define ALLOC_CHUNK 1024
31
32
33 /**
34  * gpgme_data_new:
35  * @r_dh:   Returns a new data object.
36  * @buffer: If not NULL, used to initialize the data object.
37  * @size: Size of the buffer
38  * @copy: Flag wether a copy of the buffer should be used.
39  * 
40  * Create a new data object and optionally initialize with data
41  * from the memory.  A @copy with value %TRUE creates a copy of the
42  * memory, a value of %FALSE uses the original memory of @buffer and the
43  * caller has to make sure that this buffer is valid until gpgme_release_data()
44  * is called.
45  * 
46  * Return value: 
47  **/
48 GpgmeError
49 gpgme_data_new ( GpgmeData *r_dh, const char *buffer, size_t size, int copy )
50 {
51     GpgmeData dh;
52
53     *r_dh = NULL;
54     dh = xtrycalloc ( 1, sizeof *dh );
55     if (!dh)
56         return mk_error (Out_Of_Core);
57     if ( buffer ) {
58         dh->len  = size;
59         if (copy) {
60             dh->private_buffer = xtrymalloc ( size );
61             if ( !dh->private_buffer ) {
62                 xfree (dh);
63                 return mk_error (Out_Of_Core);
64             }
65             dh->private_len = size;
66             memcpy (dh->private_buffer, buffer, size );
67             dh->data = dh->private_buffer;
68             dh->writepos = size;
69         }
70         else {
71             dh->data = buffer;
72         }
73         dh->type = GPGME_DATA_TYPE_MEM;
74     }
75     dh->mode = GPGME_DATA_MODE_INOUT; 
76     *r_dh = dh;
77     return 0;
78 }
79
80 /**
81  * gpgme_data_release:
82  * @dh: Data object 
83  * 
84  * Release the data object @dh.  @dh may be NULL in which case nothing
85  * happens.
86  **/
87 void
88 gpgme_data_release ( GpgmeData dh )
89 {
90     if (dh) {
91         xfree (dh->private_buffer); 
92         xfree (dh);
93     }
94 }
95
96
97 GpgmeDataType
98 gpgme_data_get_type ( GpgmeData dh )
99 {
100     if ( !dh || !dh->data )
101         return GPGME_DATA_TYPE_NONE;
102             
103     return dh->type;
104 }
105
106 void 
107 _gpgme_data_set_mode ( GpgmeData dh, GpgmeDataMode mode )
108 {
109     assert (dh);
110     dh->mode = mode;
111 }
112
113
114 GpgmeDataMode
115 _gpgme_data_get_mode ( GpgmeData dh )
116 {
117     assert (dh);
118     return dh->mode;
119 }
120
121 GpgmeError
122 gpgme_data_rewind ( GpgmeData dh )
123 {
124     if ( !dh )
125         return mk_error (Invalid_Value);
126     /* Fixme: We should check whether rewinding does make sense for the
127      * data type */
128     dh->readpos = 0;
129     return 0;
130 }
131
132 GpgmeError
133 gpgme_data_read ( GpgmeData dh, char *buffer, size_t length, size_t *nread )
134 {
135     size_t nbytes;
136
137     if ( !dh )
138         return mk_error (Invalid_Value);
139     nbytes = dh->len - dh->readpos;
140     if ( !nbytes ) {
141         *nread = 0;
142         return mk_error(EOF);
143     }
144     if (nbytes > length)
145         nbytes = length;
146     memcpy ( buffer, dh->data + dh->readpos, nbytes );
147     *nread = nbytes;
148     dh->readpos += nbytes;
149     return 0;
150
151
152
153 GpgmeError
154 _gpgme_data_append ( GpgmeData dh, const char *buffer, size_t length )
155 {
156     assert (dh);
157
158     if ( dh->type == GPGME_DATA_TYPE_NONE ) {
159         /* convert it to a mem data type */
160         assert (!dh->private_buffer);
161         dh->type = GPGME_DATA_TYPE_MEM;
162         dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
163         dh->private_buffer = xtrymalloc ( dh->private_len );
164         if (!dh->private_buffer) {
165             dh->private_len = 0;
166             return mk_error (Out_Of_Core);
167         }
168         dh->writepos = 0;
169         dh->data = dh->private_buffer;
170     }
171     else if ( dh->type != GPGME_DATA_TYPE_MEM ) 
172         return mk_error (Invalid_Type);
173     
174     if ( dh->mode != GPGME_DATA_MODE_INOUT 
175          && dh->mode != GPGME_DATA_MODE_IN  )
176         return mk_error (Invalid_Mode);
177
178     if ( !dh->private_buffer ) {
179         /* we have to copy it now */
180         assert (dh->data);
181         dh->private_len = dh->len+length;
182         if (dh->private_len < ALLOC_CHUNK)
183             dh->private_len = ALLOC_CHUNK;
184         dh->private_buffer = xtrymalloc ( dh->private_len );
185         if (!dh->private_buffer) {
186             dh->private_len = 0;
187             return mk_error (Out_Of_Core);
188         }
189         dh->writepos = 0;
190         dh->data = dh->private_buffer;
191     }
192
193     /* allocate more memory if needed */
194     if ( dh->writepos + length > dh->private_len ) {
195         char *p;
196         size_t newlen = dh->private_len
197                         + (dh->len < ALLOC_CHUNK? ALLOC_CHUNK : length);
198         p = xtryrealloc ( dh->private_buffer, newlen );
199         if ( !p ) 
200             return mk_error (Out_Of_Core);
201         dh->private_buffer = p;
202         dh->private_len = newlen;
203         dh->data = dh->private_buffer;
204         assert ( !(dh->writepos + length > dh->private_len) );      
205     }
206
207     memcpy ( dh->private_buffer + dh->writepos, buffer, length );
208     dh->writepos += length;
209     dh->len += length;
210
211     return 0;
212 }
213
214
215