1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
+ 8);
209 unsigned char *st
=(unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
210 #if defined __sparc__ || defined __sparc
232 /** Extract a double precision floating point number
234 * @return the extracted value
235 * @pre A suitably formatted float value must be in the buffer, else
236 * dynamic testcase error
238 double Text_Buf::pull_double()
240 if (buf_pos
+ 8 > buf_begin
+ buf_len
) TTCN_error("Text decoder: Decoding of float failed. "
241 "(End of buffer reached)");
242 const unsigned char *st
= (unsigned char *)data_ptr
+buf_pos
;
248 #if defined __sparc__ || defined __sparc
271 /** Write a fixed number of bytes in the buffer.
273 * @param len number of bytes to write
274 * @param data pointer to the data
276 void Text_Buf::push_raw(int len
, const void *data
)
278 if (len
< 0) TTCN_error("Text encoder: Encoding raw data with negative "
279 "length (%d).", len
);
280 Reallocate(buf_len
+ len
);
281 memcpy((char*)data_ptr
+ buf_begin
+ buf_len
, data
, len
);
285 /** Extract a fixed number of bytes from the buffer.
287 * @param len number of bytes to read
288 * @param data pointer to the data
289 * @pre at least \a len bytes are available, else dynamic testcase error
291 void Text_Buf::pull_raw(int len
, void *data
)
293 if (len
< 0) TTCN_error("Text decoder: Decoding raw data with negative "
294 "length (%d).", len
);
295 if (buf_pos
+ len
> buf_begin
+ buf_len
)
296 TTCN_error("Text decoder: End of buffer reached.");
297 memcpy(data
, (char*)data_ptr
+ buf_pos
, len
);
301 /** Write a 0-terminated string
303 * Writes the length followed by the raw bytes (no end marker)
305 * @param string_ptr pointer to the string
307 void Text_Buf::push_string(const char *string_ptr
)
309 if (string_ptr
!= NULL
) {
310 int len
= strlen(string_ptr
);
312 push_raw(len
, string_ptr
);
313 } else push_int((RInt
)0);
318 * @return the string allocated with new[], must be freed by the caller
320 char *Text_Buf::pull_string()
322 int len
= pull_int().get_val();
324 TTCN_error("Text decoder: Negative string length (%d).", len
);
325 char *string_ptr
= new char[len
+ 1];
326 pull_raw(len
, string_ptr
);
327 string_ptr
[len
] = '\0';
332 void Text_Buf::push_qualified_name(const qualified_name
& name
)
334 push_string(name
.module_name
);
335 push_string(name
.definition_name
);
338 /// Extract two strings
339 void Text_Buf::pull_qualified_name(qualified_name
& name
)
341 name
.module_name
= pull_string();
342 if (name
.module_name
[0] == '\0') {
343 delete [] name
.module_name
;
344 name
.module_name
= NULL
;
346 name
.definition_name
= pull_string();
347 if (name
.definition_name
[0] == '\0') {
348 delete [] name
.definition_name
;
349 name
.definition_name
= NULL
;
353 /** Calculate the length of the buffer and write it at the beginning.
356 void Text_Buf::calculate_length()
358 unsigned int value
= buf_len
;
359 unsigned int bytes_needed
= 1;
360 for (unsigned int tmp
= value
>> 6; tmp
!= 0; tmp
>>= 7) bytes_needed
++;
361 if ((unsigned int)buf_begin
< bytes_needed
)
362 TTCN_error("Text encoder: There is not enough space to calculate message "
364 unsigned char *buf
= (unsigned char*)data_ptr
+ buf_begin
- bytes_needed
;
365 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
367 buf
[i
] = value
& 0x7F;
369 } else buf
[i
] = value
& 0x3F;
370 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
373 buf_begin
-= bytes_needed
;
374 buf_len
+= bytes_needed
;
378 void Text_Buf::get_end(char*& end_ptr
, int& end_len
)
380 int buf_end
= buf_begin
+ buf_len
;
381 if (buf_size
- buf_end
< BUF_SIZE
) Reallocate(buf_len
+ BUF_SIZE
);
382 end_ptr
= (char*)data_ptr
+ buf_end
;
383 end_len
= buf_size
- buf_end
;
386 void Text_Buf::increase_length(int add_len
)
388 if (add_len
< 0) TTCN_error("Text decoder: Addition is negative (%d) when "
389 "increasing length.", add_len
);
390 if (buf_begin
+ buf_len
+ add_len
> buf_size
)
391 TTCN_error("Text decoder: Addition is too big when increasing length.");
395 /** Check if a known message is in the buffer
397 * @return TRUE if an int followed by the number of bytes specified
398 * by that int is in the buffer; FALSE otherwise.
399 * @post buf_pos == buf_begin
401 boolean
Text_Buf::is_message()
405 boolean ret_val
= FALSE
;
406 if (safe_pull_int(msg_len
)) {
408 char *tmp_str
= msg_len
.as_string();
409 TTCN_error("Text decoder: Negative message length (%s).", tmp_str
);
410 Free(tmp_str
); // ???
412 ret_val
= buf_pos
+ msg_len
.get_val() <= buf_begin
+ buf_len
;
418 /** Overwrite the extracted message with the rest of the buffer
419 * @post buf_pos == buf_begin
421 void Text_Buf::cut_message()
424 int msg_len
= pull_int().get_val();
425 int msg_end
= buf_pos
+ msg_len
;
426 buf_len
-= msg_end
- buf_begin
;
427 memmove((char*)data_ptr
+ buf_begin
, (char*)data_ptr
+ msg_end
,
This page took 0.048296 seconds and 5 git commands to generate.