1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
9 #include <stdlib.h> // for atof
14 #include "../common/memory.h"
17 #include <openssl/bn.h>
19 // Note: Do not use dbgnew.hh; it doesn't play well with Qt in mctr_gui
39 void Text_Buf::Allocate(int size
)
41 int new_buf_size
= BUF_SIZE
+ BUF_HEAD
;
42 while(new_buf_size
< size
+ buf_begin
) new_buf_size
*= 2;
43 data_ptr
= Malloc(new_buf_size
);
44 buf_size
= new_buf_size
; // always a power of 2, from 1024 up
47 void Text_Buf::Reallocate(int size
)
49 int new_buf_size
= BUF_SIZE
+ BUF_HEAD
;
50 while (new_buf_size
< size
+ buf_begin
) new_buf_size
*= 2;
51 if (new_buf_size
!= buf_size
) {
52 data_ptr
= Realloc(data_ptr
, new_buf_size
);
53 buf_size
= new_buf_size
; // always a power of 2, from 1024 up
57 void Text_Buf::reset()
65 /** Encode a native integer in the buffer
67 * @param value native integer
69 void Text_Buf::push_int(const RInt
& value
)
75 /** Encode an integer (may be bigint) into the text buffer
77 * @param value may be big integer
79 void Text_Buf::push_int(const int_val_t
& value
)
81 if (value
.is_native()) {
82 boolean is_negative
= value
< 0;
83 unsigned int unsigned_value
= is_negative
? -value
.get_val() :
85 unsigned int bytes_needed
= 1;
86 for (unsigned int tmp
= unsigned_value
>> 6; tmp
!= 0; tmp
>>= 7)
88 Reallocate(buf_len
+ bytes_needed
);
89 unsigned char *buf
= (unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
90 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
91 // The top bit is always 1 for a "middle" byte, 0 for the last byte.
92 // That leaves 7 bits, except for the first byte where the 2nd highest
93 // bit is the sign bit, so only 6 payload bits are available.
95 buf
[i
] = unsigned_value
& 0x7f;
97 } else buf
[i
] = unsigned_value
& 0x3f;
98 // Set the top bit for all but the last byte
99 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
102 if (is_negative
) buf
[0] |= 0x40; // Put in the sign bit
103 buf_len
+= bytes_needed
;
105 BIGNUM
*D
= BN_new();
106 BN_copy(D
, value
.get_val_openssl());
107 unsigned num_bits
= BN_num_bits(D
);
109 // first 6 bit +the sign bit are stored in the first octet
110 // the remaining bits stored in 7 bit group + continuation bit
111 // So how many octest needed to store the (num_bits + 1) many bits
112 // in 7 bit ber octet form?
113 // ((num_bits+1)+6)/7 =>
117 unsigned num_bytes
= (num_bits
/ 7)+1;
118 Reallocate(buf_len
+ num_bytes
);
119 unsigned char *buf
= (unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
120 for (unsigned i
= num_bytes
- 1; ; i
--) {
121 // Seven bits at a time, except the first byte has only 6 payload bits
123 buf
[i
] = D
->d
[0] & 0x7f;
124 if (!BN_rshift(D
, D
, 7)) return;
126 buf
[i
] = (D
->top
? D
->d
[0] : 0) & 0x3f;
128 if (i
< num_bytes
- 1) buf
[i
] |= 0x80;
131 if (BN_is_negative(D
)) buf
[0] |= 0x40; // Put in the sign bit
133 buf_len
+= num_bytes
;
137 /** Extract an integer from the buffer.
139 * @return the extracted value
140 * @pre An integer must be available, else dynamic testcase error
142 const int_val_t
Text_Buf::pull_int()
145 if (!safe_pull_int(value
))
146 TTCN_error("Text decoder: Decoding of integer failed.");
150 /** Extract an integer if it's safe to do so.
152 * @param[out] value set to the extracted value if successful
153 * @return TRUE if an integer could be extracted, FALSE otherwise
155 boolean
Text_Buf::safe_pull_int(int_val_t
& value
)
157 int buf_end
= buf_begin
+ buf_len
;
158 if (buf_pos
>= buf_end
) return FALSE
;
160 // Count continuation flags.
161 while (pos
< buf_end
&& ((unsigned char *)data_ptr
)[pos
] & 0x80) pos
++;
162 if (pos
>= buf_end
) return FALSE
;
163 unsigned int bytes_needed
= pos
- buf_pos
+ 1;
164 const unsigned char *buf
= (unsigned char *)data_ptr
+ buf_pos
;
165 if (bytes_needed
> sizeof(RInt
)) {
166 BIGNUM
*D
= BN_new();
169 for (unsigned i
= 0; i
< bytes_needed
; i
++) {
170 // TTCN-TCC-INTERNAL-0026 (HJ87126)
171 if (i
> 0) BN_add_word(D
, buf
[i
] & 0x7f);
172 else BN_add_word(D
, buf
[i
] & 0x3f);
173 if (i
< bytes_needed
- 1)
176 if (buf
[0] & 0x40) { neg
= 1; BN_set_negative(D
, 1); }
177 if (BN_num_bits(D
) > (RInt
)sizeof(RInt
) * 8 - 1) {
178 value
= int_val_t(D
);
180 value
= int_val_t(neg
? -D
->d
[0] : D
->d
[0]);
184 unsigned long loc_value
= 0;
185 for (unsigned i
= 0; i
< bytes_needed
; i
++) {
186 if (i
> 0) loc_value
|= buf
[i
] & 0x7f;
187 else loc_value
|= buf
[i
] & 0x3f;
188 if (i
< bytes_needed
- 1) loc_value
<<= 7;
190 if (buf
[0] & 0x40) value
= -loc_value
;
191 else value
= loc_value
;
197 /** Encode a double precision floating point number in the buffer.
201 void Text_Buf::push_double(double value
)
203 Reallocate(buf_len
+ 32);
204 buf_len
+= sprintf((char*)data_ptr
+ buf_begin
+ buf_len
, "%.16g ", value
);
207 /** Extract a double precision floating point number
209 * @return the extracted value
210 * @pre A suitably formatted float value must be in the buffer, else
211 * dynamic testcase error
213 double Text_Buf::pull_double()
215 int buf_end
= buf_begin
+ buf_len
;
216 const char *char_ptr
= (const char*)data_ptr
;
217 // check for the proper format (printed in ascii, followed by a space)
218 if (buf_pos
>= buf_end
) TTCN_error("Text decoder: Decoding of float failed. "
219 "(End of buffer reached)");
220 else if (char_ptr
[buf_pos
] == ' ') TTCN_error("Text decoder: Decoding of "
221 "float failed. (No data before the end marker)");
222 int end_pos
= buf_pos
+ 1;
223 for ( ; ; end_pos
++) {
224 if (end_pos
>= buf_end
) TTCN_error("Text decoder: Decoding of float "
225 "failed. (Missing end marker)");
226 else if (char_ptr
[end_pos
] == ' ') break;
228 // perform the decoding
230 double ret_val
= atof(char_ptr
+ buf_pos
);
231 if (ret_val
== 0.0 && errno
!= 0) TTCN_error("Text decoder: Decoding of "
233 // increment the read pointer
234 buf_pos
= end_pos
+ 1;
238 /** Write a fixed number of bytes in the buffer.
240 * @param len number of bytes to write
241 * @param data pointer to the data
243 void Text_Buf::push_raw(int len
, const void *data
)
245 if (len
< 0) TTCN_error("Text encoder: Encoding raw data with negative "
246 "length (%d).", len
);
247 Reallocate(buf_len
+ len
);
248 memcpy((char*)data_ptr
+ buf_begin
+ buf_len
, data
, len
);
252 /** Extract a fixed number of bytes from the buffer.
254 * @param len number of bytes to read
255 * @param data pointer to the data
256 * @pre at least \a len bytes are available, else dynamic testcase error
258 void Text_Buf::pull_raw(int len
, void *data
)
260 if (len
< 0) TTCN_error("Text decoder: Decoding raw data with negative "
261 "length (%d).", len
);
262 if (buf_pos
+ len
> buf_begin
+ buf_len
)
263 TTCN_error("Text decoder: End of buffer reached.");
264 memcpy(data
, (char*)data_ptr
+ buf_pos
, len
);
268 /** Write a 0-terminated string
270 * Writes the length followed by the raw bytes (no end marker)
272 * @param string_ptr pointer to the string
274 void Text_Buf::push_string(const char *string_ptr
)
276 if (string_ptr
!= NULL
) {
277 int len
= strlen(string_ptr
);
279 push_raw(len
, string_ptr
);
280 } else push_int((RInt
)0);
285 * @return the string allocated with new[], must be freed by the caller
287 char *Text_Buf::pull_string()
289 int len
= pull_int().get_val();
291 TTCN_error("Text decoder: Negative string length (%d).", len
);
292 char *string_ptr
= new char[len
+ 1];
293 pull_raw(len
, string_ptr
);
294 string_ptr
[len
] = '\0';
299 void Text_Buf::push_qualified_name(const qualified_name
& name
)
301 push_string(name
.module_name
);
302 push_string(name
.definition_name
);
305 /// Extract two strings
306 void Text_Buf::pull_qualified_name(qualified_name
& name
)
308 name
.module_name
= pull_string();
309 if (name
.module_name
[0] == '\0') {
310 delete [] name
.module_name
;
311 name
.module_name
= NULL
;
313 name
.definition_name
= pull_string();
314 if (name
.definition_name
[0] == '\0') {
315 delete [] name
.definition_name
;
316 name
.definition_name
= NULL
;
320 /** Calculate the length of the buffer and write it at the beginning.
323 void Text_Buf::calculate_length()
325 unsigned int value
= buf_len
;
326 unsigned int bytes_needed
= 1;
327 for (unsigned int tmp
= value
>> 6; tmp
!= 0; tmp
>>= 7) bytes_needed
++;
328 if ((unsigned int)buf_begin
< bytes_needed
)
329 TTCN_error("Text encoder: There is not enough space to calculate message "
331 unsigned char *buf
= (unsigned char*)data_ptr
+ buf_begin
- bytes_needed
;
332 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
334 buf
[i
] = value
& 0x7F;
336 } else buf
[i
] = value
& 0x3F;
337 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
340 buf_begin
-= bytes_needed
;
341 buf_len
+= bytes_needed
;
345 void Text_Buf::get_end(char*& end_ptr
, int& end_len
)
347 int buf_end
= buf_begin
+ buf_len
;
348 if (buf_size
- buf_end
< BUF_SIZE
) Reallocate(buf_len
+ BUF_SIZE
);
349 end_ptr
= (char*)data_ptr
+ buf_end
;
350 end_len
= buf_size
- buf_end
;
353 void Text_Buf::increase_length(int add_len
)
355 if (add_len
< 0) TTCN_error("Text decoder: Addition is negative (%d) when "
356 "increasing length.", add_len
);
357 if (buf_begin
+ buf_len
+ add_len
> buf_size
)
358 TTCN_error("Text decoder: Addition is too big when increasing length.");
362 /** Check if a known message is in the buffer
364 * @return TRUE if an int followed by the number of bytes specified
365 * by that int is in the buffer; FALSE otherwise.
366 * @post buf_pos == buf_begin
368 boolean
Text_Buf::is_message()
372 boolean ret_val
= FALSE
;
373 if (safe_pull_int(msg_len
)) {
375 char *tmp_str
= msg_len
.as_string();
376 TTCN_error("Text decoder: Negative message length (%s).", tmp_str
);
377 Free(tmp_str
); // ???
379 ret_val
= buf_pos
+ msg_len
.get_val() <= buf_begin
+ buf_len
;
385 /** Overwrite the extracted message with the rest of the buffer
386 * @post buf_pos == buf_begin
388 void Text_Buf::cut_message()
391 int msg_len
= pull_int().get_val();
392 int msg_end
= buf_pos
+ msg_len
;
393 buf_len
-= msg_end
- buf_begin
;
394 memmove((char*)data_ptr
+ buf_begin
, (char*)data_ptr
+ msg_end
,
This page took 0.040332 seconds and 6 git commands to generate.