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 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 
31 #ifdef VRTX
32 #define __READY_EXTENSIONS__
33 #include <errno.h>
34 #endif
35 
36 #include "eidef.h"
37 #include "ei_x_encode.h"
38 #include "ei_malloc.h"
39 
40 int ei_x_extra = 100;
41 
ei_x_new(ei_x_buff * x)42 int ei_x_new(ei_x_buff* x)
43 {
44     x->buff = ei_malloc(ei_x_extra);
45     x->buffsz = ei_x_extra;
46     x->index = 0;
47     return x->buff != NULL ? 0 : -1;
48 }
49 
ei_x_new_with_version(ei_x_buff * x)50 int ei_x_new_with_version(ei_x_buff* x)
51 {
52     if (ei_x_new(x) < 0)
53 	return -1;
54     return ei_encode_version(x->buff, &x->index);
55 }
56 
ei_x_free(ei_x_buff * x)57 int ei_x_free(ei_x_buff* x)
58 {
59     if (x->buff == NULL)
60 	return -1;
61     ei_free(x->buff);
62     x->buff = NULL;
63     return 0;
64 }
65 
x_fix_buff(ei_x_buff * x,int szneeded)66 int x_fix_buff(ei_x_buff* x, int szneeded)
67 {
68     int sz = szneeded + ei_x_extra;
69     if (sz > x->buffsz) {
70 	sz += ei_x_extra;	/* to avoid reallocating each and every time */
71 	x->buffsz = sz;
72 	x->buff = ei_realloc(x->buff, sz);
73     }
74     return x->buff != NULL;
75 }
76 
ei_x_append(ei_x_buff * x,const ei_x_buff * x2)77 int ei_x_append(ei_x_buff* x, const ei_x_buff* x2)
78 {
79     return ei_x_append_buf(x, x2->buff, x2->index);
80 }
81 
ei_x_append_buf(ei_x_buff * x,const char * buf,int len)82 int ei_x_append_buf(ei_x_buff* x, const char* buf, int len)
83 {
84     if (!x_fix_buff(x, x->index+len))
85 	return -1;
86     memcpy(&x->buff[x->index], buf, len);
87     x->index += len;
88     return 0;
89 }
90 
ei_x_encode_string(ei_x_buff * x,const char * s)91 int ei_x_encode_string(ei_x_buff* x, const char* s)
92 {
93     return ei_x_encode_string_len(x, s, strlen(s));
94 }
95 
ei_x_encode_string_len(ei_x_buff * x,const char * s,int len)96 int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)
97 {
98     int i = x->index;
99     if (ei_encode_string_len(NULL, &i, s, len) == -1)
100       return -1;
101     if (!x_fix_buff(x, i))
102 	return -1;
103     return ei_encode_string_len(x->buff, &x->index, s, len);
104 }
105 
ei_x_encode_binary(ei_x_buff * x,const void * p,int len)106 int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
107 {
108     int i = x->index;
109     if (ei_encode_binary(NULL, &i, p, len) == -1)
110       return -1;
111     if (!x_fix_buff(x, i))
112 	return -1;
113     return ei_encode_binary(x->buff, &x->index, p, len);
114 }
115 
ei_x_encode_bitstring(ei_x_buff * x,const char * p,size_t bitoffs,size_t bits)116 int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits)
117 {
118     int i = x->index;
119     if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1)
120       return -1;
121     if (!x_fix_buff(x, i))
122 	return -1;
123     return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits);
124 }
125 
ei_x_encode_long(ei_x_buff * x,long n)126 int ei_x_encode_long(ei_x_buff* x, long n)
127 {
128     int i = x->index;
129     if (ei_encode_long(NULL, &i, n) == -1)
130       return -1;
131     if (!x_fix_buff(x, i))
132 	return -1;
133     return ei_encode_long(x->buff, &x->index, n);
134 }
135 
ei_x_encode_ulong(ei_x_buff * x,unsigned long n)136 int ei_x_encode_ulong(ei_x_buff* x, unsigned long n)
137 {
138     int i = x->index;
139     if (ei_encode_ulong(NULL, &i, n) == -1)
140       return -1;
141     if (!x_fix_buff(x, i))
142 	return -1;
143     return ei_encode_ulong(x->buff, &x->index, n);
144 }
145 
ei_x_encode_char(ei_x_buff * x,char p)146 int ei_x_encode_char(ei_x_buff* x, char p)
147 {
148     int i = x->index;
149     if (ei_encode_char(NULL, &i, p) == -1)
150       return -1;
151     if (!x_fix_buff(x, i))
152 	return -1;
153     return ei_encode_char(x->buff, &x->index, p);
154 }
155 
ei_x_encode_boolean(ei_x_buff * x,int p)156 int ei_x_encode_boolean(ei_x_buff* x, int p)
157 {
158     int i = x->index;
159     if (ei_encode_boolean(NULL, &i, p) == -1)
160       return -1;
161     if (!x_fix_buff(x, i))
162 	return -1;
163     return ei_encode_boolean(x->buff, &x->index, p);
164 }
165 
ei_x_encode_double(ei_x_buff * x,double dbl)166 int ei_x_encode_double(ei_x_buff* x, double dbl)
167 {
168     int i = x->index;
169     if (ei_encode_double(NULL, &i, dbl) == -1)
170       return -1;
171     if (!x_fix_buff(x, i))
172 	return -1;
173     return ei_encode_double(x->buff, &x->index, dbl);
174 }
175 
ei_x_encode_list_header(ei_x_buff * x,long n)176 int ei_x_encode_list_header(ei_x_buff* x, long n)
177 {
178     int i = x->index;
179     if (ei_encode_list_header(NULL, &i, n) == -1)
180       return -1;
181     if (!x_fix_buff(x, i))
182 	return -1;
183     return ei_encode_list_header(x->buff, &x->index, n);
184 }
185 
ei_x_encode_empty_list(ei_x_buff * x)186 int ei_x_encode_empty_list(ei_x_buff* x)
187 {
188     int i = x->index;
189     if (ei_encode_empty_list(NULL, &i) == -1)
190       return -1;
191     if (!x_fix_buff(x, i))
192 	return -1;
193     return ei_encode_empty_list(x->buff, &x->index);
194 }
195 
ei_x_encode_version(ei_x_buff * x)196 int ei_x_encode_version(ei_x_buff* x)
197 {
198     int i = x->index;
199     if (ei_encode_version(NULL, &i) == -1)
200       return -1;
201     if (!x_fix_buff(x, i))
202 	return -1;
203     return ei_encode_version(x->buff, &x->index);
204 }
205 
ei_x_encode_tuple_header(ei_x_buff * x,long n)206 int ei_x_encode_tuple_header(ei_x_buff* x, long n)
207 {
208     int i = x->index;
209     if (ei_encode_tuple_header(NULL, &i, n) == -1)
210       return -1;
211     if (!x_fix_buff(x, i))
212 	return -1;
213     return ei_encode_tuple_header(x->buff, &x->index, n);
214 }
215 
ei_x_encode_map_header(ei_x_buff * x,long n)216 int ei_x_encode_map_header(ei_x_buff* x, long n)
217 {
218     int i = x->index;
219     if (ei_encode_map_header(NULL, &i, n) == -1)
220       return -1;
221     if (!x_fix_buff(x, i))
222 	return -1;
223     return ei_encode_map_header(x->buff, &x->index, n);
224 }
225 
ei_x_encode_atom(ei_x_buff * x,const char * s)226 int ei_x_encode_atom(ei_x_buff* x, const char* s)
227 {
228     return ei_x_encode_atom_len_as(x, s, strlen(s), ERLANG_LATIN1, ERLANG_LATIN1);
229 }
230 
ei_x_encode_atom_len(ei_x_buff * x,const char * s,int len)231 int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len)
232 {
233     return ei_x_encode_atom_len_as(x, s, len, ERLANG_LATIN1, ERLANG_LATIN1);
234 }
235 
ei_x_encode_atom_as(ei_x_buff * x,const char * s,erlang_char_encoding from_enc,erlang_char_encoding to_enc)236 int ei_x_encode_atom_as(ei_x_buff* x, const char* s,
237 			erlang_char_encoding from_enc,
238 			erlang_char_encoding to_enc)
239 {
240     return ei_x_encode_atom_len_as(x, s, strlen(s), from_enc, to_enc);
241 }
242 
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)243 int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
244 			    erlang_char_encoding from_enc,
245 			    erlang_char_encoding to_enc)
246 {
247     int i = x->index;
248     if (ei_encode_atom_len_as(NULL, &i, s, len, from_enc, to_enc) == -1)
249       return -1;
250     if (!x_fix_buff(x, i))
251 	return -1;
252     return ei_encode_atom_len_as(x->buff, &x->index, s, len, from_enc, to_enc);
253 }
254 
255 
ei_x_encode_pid(ei_x_buff * x,const erlang_pid * pid)256 int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid)
257 {
258     int i = x->index;
259     if (ei_encode_pid(NULL, &i, pid) == -1)
260       return -1;
261     if (!x_fix_buff(x, i))
262 	return -1;
263     return ei_encode_pid(x->buff, &x->index, pid);
264 }
265 
ei_x_encode_fun(ei_x_buff * x,const erlang_fun * fun)266 int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)
267 {
268     int i = x->index;
269     if (ei_encode_fun(NULL, &i, fun) == -1)
270       return -1;
271     if (!x_fix_buff(x, i))
272 	return -1;
273     return ei_encode_fun(x->buff, &x->index, fun);
274 }
275 
ei_x_encode_ref(ei_x_buff * x,const erlang_ref * ref)276 int ei_x_encode_ref(ei_x_buff* x, const erlang_ref* ref)
277 {
278     int i = x->index;
279     if (ei_encode_ref(NULL, &i, ref) == -1)
280       return -1;
281     if (!x_fix_buff(x, i))
282 	return -1;
283     return ei_encode_ref(x->buff, &x->index, ref);
284 }
285 
ei_x_encode_port(ei_x_buff * x,const erlang_port * port)286 int ei_x_encode_port(ei_x_buff* x, const erlang_port* port)
287 {
288     int i = x->index;
289     if (ei_encode_port(NULL, &i, port) == -1)
290       return -1;
291     if (!x_fix_buff(x, i))
292 	return -1;
293     return ei_encode_port(x->buff, &x->index, port);
294 }
295 
ei_x_encode_trace(ei_x_buff * x,const erlang_trace * trace)296 int ei_x_encode_trace(ei_x_buff* x, const erlang_trace* trace)
297 {
298     int i = x->index;
299     if (ei_encode_trace(NULL, &i, trace) == -1)
300       return -1;
301     if (!x_fix_buff(x, i))
302 	return -1;
303     return ei_encode_trace(x->buff, &x->index, trace);
304 }
305