1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2001-2020. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  *
20 
21  */
22 /*
23  * ei_x_encode to encode in a self-expanding buffer
24  */
25 
26 #ifdef VXWORKS
27 #include <vxWorks.h>
28 #endif
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #ifdef VRTX
36 #define __READY_EXTENSIONS__
37 #include <errno.h>
38 #endif
39 
40 #include "eidef.h"
41 #include "ei_x_encode.h"
42 #include "ei_malloc.h"
43 
44 int ei_x_extra = 100;
45 
ei_x_new(ei_x_buff * x)46 int ei_x_new(ei_x_buff* x)
47 {
48     x->buff = ei_malloc(ei_x_extra);
49     x->buffsz = ei_x_extra;
50     x->index = 0;
51     return x->buff != NULL ? 0 : -1;
52 }
53 
ei_x_new_with_version(ei_x_buff * x)54 int ei_x_new_with_version(ei_x_buff* x)
55 {
56     if (ei_x_new(x) < 0)
57 	return -1;
58     return ei_encode_version(x->buff, &x->index);
59 }
60 
ei_x_free(ei_x_buff * x)61 int ei_x_free(ei_x_buff* x)
62 {
63     if (x->buff == NULL)
64 	return -1;
65     ei_free(x->buff);
66     x->buff = NULL;
67     return 0;
68 }
69 
x_fix_buff(ei_x_buff * x,int szneeded)70 int x_fix_buff(ei_x_buff* x, int szneeded)
71 {
72     int sz = szneeded + ei_x_extra;
73     if (sz > x->buffsz) {
74 	sz += ei_x_extra;	/* to avoid reallocating each and every time */
75 	x->buffsz = sz;
76 	x->buff = ei_realloc(x->buff, sz);
77     }
78     return x->buff != NULL;
79 }
80 
ei_x_append(ei_x_buff * x,const ei_x_buff * x2)81 int ei_x_append(ei_x_buff* x, const ei_x_buff* x2)
82 {
83     return ei_x_append_buf(x, x2->buff, x2->index);
84 }
85 
ei_x_append_buf(ei_x_buff * x,const char * buf,int len)86 int ei_x_append_buf(ei_x_buff* x, const char* buf, int len)
87 {
88     if (!x_fix_buff(x, x->index+len))
89 	return -1;
90     memcpy(&x->buff[x->index], buf, len);
91     x->index += len;
92     return 0;
93 }
94 
ei_x_encode_string(ei_x_buff * x,const char * s)95 int ei_x_encode_string(ei_x_buff* x, const char* s)
96 {
97     return ei_x_encode_string_len(x, s, strlen(s));
98 }
99 
ei_x_encode_string_len(ei_x_buff * x,const char * s,int len)100 int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)
101 {
102     int i = x->index;
103     if (ei_encode_string_len(NULL, &i, s, len) == -1)
104       return -1;
105     if (!x_fix_buff(x, i))
106 	return -1;
107     return ei_encode_string_len(x->buff, &x->index, s, len);
108 }
109 
ei_x_encode_binary(ei_x_buff * x,const void * p,int len)110 int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
111 {
112     int i = x->index;
113     if (ei_encode_binary(NULL, &i, p, len) == -1)
114       return -1;
115     if (!x_fix_buff(x, i))
116 	return -1;
117     return ei_encode_binary(x->buff, &x->index, p, len);
118 }
119 
ei_x_encode_bitstring(ei_x_buff * x,const char * p,size_t bitoffs,size_t bits)120 int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits)
121 {
122     int i = x->index;
123     if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1)
124       return -1;
125     if (!x_fix_buff(x, i))
126 	return -1;
127     return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits);
128 }
129 
ei_x_encode_long(ei_x_buff * x,long n)130 int ei_x_encode_long(ei_x_buff* x, long n)
131 {
132     int i = x->index;
133     if (ei_encode_long(NULL, &i, n) == -1)
134       return -1;
135     if (!x_fix_buff(x, i))
136 	return -1;
137     return ei_encode_long(x->buff, &x->index, n);
138 }
139 
ei_x_encode_ulong(ei_x_buff * x,unsigned long n)140 int ei_x_encode_ulong(ei_x_buff* x, unsigned long n)
141 {
142     int i = x->index;
143     if (ei_encode_ulong(NULL, &i, n) == -1)
144       return -1;
145     if (!x_fix_buff(x, i))
146 	return -1;
147     return ei_encode_ulong(x->buff, &x->index, n);
148 }
149 
ei_x_encode_char(ei_x_buff * x,char p)150 int ei_x_encode_char(ei_x_buff* x, char p)
151 {
152     int i = x->index;
153     if (ei_encode_char(NULL, &i, p) == -1)
154       return -1;
155     if (!x_fix_buff(x, i))
156 	return -1;
157     return ei_encode_char(x->buff, &x->index, p);
158 }
159 
ei_x_encode_boolean(ei_x_buff * x,int p)160 int ei_x_encode_boolean(ei_x_buff* x, int p)
161 {
162     int i = x->index;
163     if (ei_encode_boolean(NULL, &i, p) == -1)
164       return -1;
165     if (!x_fix_buff(x, i))
166 	return -1;
167     return ei_encode_boolean(x->buff, &x->index, p);
168 }
169 
ei_x_encode_double(ei_x_buff * x,double dbl)170 int ei_x_encode_double(ei_x_buff* x, double dbl)
171 {
172     int i = x->index;
173     if (ei_encode_double(NULL, &i, dbl) == -1)
174       return -1;
175     if (!x_fix_buff(x, i))
176 	return -1;
177     return ei_encode_double(x->buff, &x->index, dbl);
178 }
179 
ei_x_encode_list_header(ei_x_buff * x,long n)180 int ei_x_encode_list_header(ei_x_buff* x, long n)
181 {
182     int i = x->index;
183     if (ei_encode_list_header(NULL, &i, n) == -1)
184       return -1;
185     if (!x_fix_buff(x, i))
186 	return -1;
187     return ei_encode_list_header(x->buff, &x->index, n);
188 }
189 
ei_x_encode_empty_list(ei_x_buff * x)190 int ei_x_encode_empty_list(ei_x_buff* x)
191 {
192     int i = x->index;
193     if (ei_encode_empty_list(NULL, &i) == -1)
194       return -1;
195     if (!x_fix_buff(x, i))
196 	return -1;
197     return ei_encode_empty_list(x->buff, &x->index);
198 }
199 
ei_x_encode_version(ei_x_buff * x)200 int ei_x_encode_version(ei_x_buff* x)
201 {
202     int i = x->index;
203     if (ei_encode_version(NULL, &i) == -1)
204       return -1;
205     if (!x_fix_buff(x, i))
206 	return -1;
207     return ei_encode_version(x->buff, &x->index);
208 }
209 
ei_x_encode_tuple_header(ei_x_buff * x,long n)210 int ei_x_encode_tuple_header(ei_x_buff* x, long n)
211 {
212     int i = x->index;
213     if (ei_encode_tuple_header(NULL, &i, n) == -1)
214       return -1;
215     if (!x_fix_buff(x, i))
216 	return -1;
217     return ei_encode_tuple_header(x->buff, &x->index, n);
218 }
219 
ei_x_encode_map_header(ei_x_buff * x,long n)220 int ei_x_encode_map_header(ei_x_buff* x, long n)
221 {
222     int i = x->index;
223     if (ei_encode_map_header(NULL, &i, n) == -1)
224       return -1;
225     if (!x_fix_buff(x, i))
226 	return -1;
227     return ei_encode_map_header(x->buff, &x->index, n);
228 }
229 
ei_x_encode_atom(ei_x_buff * x,const char * s)230 int ei_x_encode_atom(ei_x_buff* x, const char* s)
231 {
232     return ei_x_encode_atom_len_as(x, s, strlen(s), ERLANG_LATIN1, ERLANG_LATIN1);
233 }
234 
ei_x_encode_atom_len(ei_x_buff * x,const char * s,int len)235 int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len)
236 {
237     return ei_x_encode_atom_len_as(x, s, len, ERLANG_LATIN1, ERLANG_LATIN1);
238 }
239 
ei_x_encode_atom_as(ei_x_buff * x,const char * s,erlang_char_encoding from_enc,erlang_char_encoding to_enc)240 int ei_x_encode_atom_as(ei_x_buff* x, const char* s,
241 			erlang_char_encoding from_enc,
242 			erlang_char_encoding to_enc)
243 {
244     return ei_x_encode_atom_len_as(x, s, strlen(s), from_enc, to_enc);
245 }
246 
ei_x_encode_atom_len_as(ei_x_buff * x,const char * s,int len,erlang_char_encoding from_enc,erlang_char_encoding to_enc)247 int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
248 			    erlang_char_encoding from_enc,
249 			    erlang_char_encoding to_enc)
250 {
251     int i = x->index;
252     if (ei_encode_atom_len_as(NULL, &i, s, len, from_enc, to_enc) == -1)
253       return -1;
254     if (!x_fix_buff(x, i))
255 	return -1;
256     return ei_encode_atom_len_as(x->buff, &x->index, s, len, from_enc, to_enc);
257 }
258 
259 
ei_x_encode_pid(ei_x_buff * x,const erlang_pid * pid)260 int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid)
261 {
262     int i = x->index;
263     if (ei_encode_pid(NULL, &i, pid) == -1)
264       return -1;
265     if (!x_fix_buff(x, i))
266 	return -1;
267     return ei_encode_pid(x->buff, &x->index, pid);
268 }
269 
ei_x_encode_fun(ei_x_buff * x,const erlang_fun * fun)270 int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)
271 {
272     int i = x->index;
273     if (ei_encode_fun(NULL, &i, fun) == -1)
274       return -1;
275     if (!x_fix_buff(x, i))
276 	return -1;
277     return ei_encode_fun(x->buff, &x->index, fun);
278 }
279 
ei_x_encode_ref(ei_x_buff * x,const erlang_ref * ref)280 int ei_x_encode_ref(ei_x_buff* x, const erlang_ref* ref)
281 {
282     int i = x->index;
283     if (ei_encode_ref(NULL, &i, ref) == -1)
284       return -1;
285     if (!x_fix_buff(x, i))
286 	return -1;
287     return ei_encode_ref(x->buff, &x->index, ref);
288 }
289 
ei_x_encode_port(ei_x_buff * x,const erlang_port * port)290 int ei_x_encode_port(ei_x_buff* x, const erlang_port* port)
291 {
292     int i = x->index;
293     if (ei_encode_port(NULL, &i, port) == -1)
294       return -1;
295     if (!x_fix_buff(x, i))
296 	return -1;
297     return ei_encode_port(x->buff, &x->index, port);
298 }
299 
ei_x_encode_trace(ei_x_buff * x,const erlang_trace * trace)300 int ei_x_encode_trace(ei_x_buff* x, const erlang_trace* trace)
301 {
302     int i = x->index;
303     if (ei_encode_trace(NULL, &i, trace) == -1)
304       return -1;
305     if (!x_fix_buff(x, i))
306 	return -1;
307     return ei_encode_trace(x->buff, &x->index, trace);
308 }
309