1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
13 * Szabo, Janos Zoltan – initial implementation
16 ******************************************************************************/
18 #include <stdlib.h> // for atof
23 #include "../common/memory.h"
26 #include <openssl/bn.h>
28 // Note: Do not use dbgnew.hh; it doesn't play well with Qt in mctr_gui
48 void Text_Buf::Allocate(int size
)
50 int new_buf_size
= BUF_SIZE
+ BUF_HEAD
;
51 while(new_buf_size
< size
+ buf_begin
) new_buf_size
*= 2;
52 data_ptr
= Malloc(new_buf_size
);
53 buf_size
= new_buf_size
; // always a power of 2, from 1024 up
56 void Text_Buf::Reallocate(int size
)
58 int new_buf_size
= BUF_SIZE
+ BUF_HEAD
;
59 while (new_buf_size
< size
+ buf_begin
) new_buf_size
*= 2;
60 if (new_buf_size
!= buf_size
) {
61 data_ptr
= Realloc(data_ptr
, new_buf_size
);
62 buf_size
= new_buf_size
; // always a power of 2, from 1024 up
66 void Text_Buf::reset()
74 /** Encode a native integer in the buffer
76 * @param value native integer
78 void Text_Buf::push_int(const RInt
& value
)
84 /** Encode an integer (may be bigint) into the text buffer
86 * @param value may be big integer
88 void Text_Buf::push_int(const int_val_t
& value
)
90 if (value
.is_native()) {
91 boolean is_negative
= value
< 0;
92 unsigned int unsigned_value
= is_negative
? -value
.get_val() :
94 unsigned int bytes_needed
= 1;
95 for (unsigned int tmp
= unsigned_value
>> 6; tmp
!= 0; tmp
>>= 7)
97 Reallocate(buf_len
+ bytes_needed
);
98 unsigned char *buf
= (unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
99 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
100 // The top bit is always 1 for a "middle" byte, 0 for the last byte.
101 // That leaves 7 bits, except for the first byte where the 2nd highest
102 // bit is the sign bit, so only 6 payload bits are available.
104 buf
[i
] = unsigned_value
& 0x7f;
105 unsigned_value
>>= 7;
106 } else buf
[i
] = unsigned_value
& 0x3f;
107 // Set the top bit for all but the last byte
108 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
111 if (is_negative
) buf
[0] |= 0x40; // Put in the sign bit
112 buf_len
+= bytes_needed
;
114 BIGNUM
*D
= BN_new();
115 BN_copy(D
, value
.get_val_openssl());
116 unsigned num_bits
= BN_num_bits(D
);
118 // first 6 bit +the sign bit are stored in the first octet
119 // the remaining bits stored in 7 bit group + continuation bit
120 // So how many octest needed to store the (num_bits + 1) many bits
121 // in 7 bit ber octet form?
122 // ((num_bits+1)+6)/7 =>
126 unsigned num_bytes
= (num_bits
/ 7)+1;
127 Reallocate(buf_len
+ num_bytes
);
128 unsigned char *buf
= (unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
129 for (unsigned i
= num_bytes
- 1; ; i
--) {
130 // Seven bits at a time, except the first byte has only 6 payload bits
132 buf
[i
] = D
->d
[0] & 0x7f;
133 if (!BN_rshift(D
, D
, 7)) return;
135 buf
[i
] = (D
->top
? D
->d
[0] : 0) & 0x3f;
137 if (i
< num_bytes
- 1) buf
[i
] |= 0x80;
140 if (BN_is_negative(D
)) buf
[0] |= 0x40; // Put in the sign bit
142 buf_len
+= num_bytes
;
146 /** Extract an integer from the buffer.
148 * @return the extracted value
149 * @pre An integer must be available, else dynamic testcase error
151 const int_val_t
Text_Buf::pull_int()
154 if (!safe_pull_int(value
))
155 TTCN_error("Text decoder: Decoding of integer failed.");
159 /** Extract an integer if it's safe to do so.
161 * @param[out] value set to the extracted value if successful
162 * @return TRUE if an integer could be extracted, FALSE otherwise
164 boolean
Text_Buf::safe_pull_int(int_val_t
& value
)
166 int buf_end
= buf_begin
+ buf_len
;
167 if (buf_pos
>= buf_end
) return FALSE
;
169 // Count continuation flags.
170 while (pos
< buf_end
&& ((unsigned char *)data_ptr
)[pos
] & 0x80) pos
++;
171 if (pos
>= buf_end
) return FALSE
;
172 unsigned int bytes_needed
= pos
- buf_pos
+ 1;
173 const unsigned char *buf
= (unsigned char *)data_ptr
+ buf_pos
;
174 if (bytes_needed
> sizeof(RInt
)) {
175 BIGNUM
*D
= BN_new();
178 for (unsigned i
= 0; i
< bytes_needed
; i
++) {
179 // TTCN-TCC-INTERNAL-0026 (HJ87126)
180 if (i
> 0) BN_add_word(D
, buf
[i
] & 0x7f);
181 else BN_add_word(D
, buf
[i
] & 0x3f);
182 if (i
< bytes_needed
- 1)
185 if (buf
[0] & 0x40) { neg
= 1; BN_set_negative(D
, 1); }
186 if (BN_num_bits(D
) > (RInt
)sizeof(RInt
) * 8 - 1) {
187 value
= int_val_t(D
);
189 value
= int_val_t(neg
? -D
->d
[0] : D
->d
[0]);
193 unsigned long loc_value
= 0;
194 for (unsigned i
= 0; i
< bytes_needed
; i
++) {
195 if (i
> 0) loc_value
|= buf
[i
] & 0x7f;
196 else loc_value
|= buf
[i
] & 0x3f;
197 if (i
< bytes_needed
- 1) loc_value
<<= 7;
199 if (buf
[0] & 0x40) value
= -loc_value
;
200 else value
= loc_value
;
206 /** Encode a double precision floating point number in the buffer.
210 void Text_Buf::push_double(double value
)
212 Reallocate(buf_len
+ 8);
218 unsigned char *st
=(unsigned char *)data_ptr
+ buf_begin
+ buf_len
;
219 #if defined __sparc__ || defined __sparc
241 /** Extract a double precision floating point number
243 * @return the extracted value
244 * @pre A suitably formatted float value must be in the buffer, else
245 * dynamic testcase error
247 double Text_Buf::pull_double()
249 if (buf_pos
+ 8 > buf_begin
+ buf_len
) TTCN_error("Text decoder: Decoding of float failed. "
250 "(End of buffer reached)");
251 const unsigned char *st
= (unsigned char *)data_ptr
+buf_pos
;
257 #if defined __sparc__ || defined __sparc
280 /** Write a fixed number of bytes in the buffer.
282 * @param len number of bytes to write
283 * @param data pointer to the data
285 void Text_Buf::push_raw(int len
, const void *data
)
287 if (len
< 0) TTCN_error("Text encoder: Encoding raw data with negative "
288 "length (%d).", len
);
289 Reallocate(buf_len
+ len
);
290 memcpy((char*)data_ptr
+ buf_begin
+ buf_len
, data
, len
);
294 void Text_Buf::push_raw_front(int len
, const void* data
)
296 if (len
< 0) TTCN_error("Text encoder: Encoding raw data with negative "
297 "length (%d).", len
);
298 Reallocate(buf_len
+ len
);
299 for (int i
= buf_len
- 1; i
>= 0; --i
) {
300 ((char*)data_ptr
)[buf_begin
+ len
+ i
] = ((char*)data_ptr
)[buf_begin
+ i
];
302 memcpy((char*)data_ptr
+ buf_begin
, data
, len
);
306 /** Extract a fixed number of bytes from the buffer.
308 * @param len number of bytes to read
309 * @param data pointer to the data
310 * @pre at least \a len bytes are available, else dynamic testcase error
312 void Text_Buf::pull_raw(int len
, void *data
)
314 if (len
< 0) TTCN_error("Text decoder: Decoding raw data with negative "
315 "length (%d).", len
);
316 if (buf_pos
+ len
> buf_begin
+ buf_len
)
317 TTCN_error("Text decoder: End of buffer reached.");
318 memcpy(data
, (char*)data_ptr
+ buf_pos
, len
);
322 /** Write a 0-terminated string
324 * Writes the length followed by the raw bytes (no end marker)
326 * @param string_ptr pointer to the string
328 void Text_Buf::push_string(const char *string_ptr
)
330 if (string_ptr
!= NULL
) {
331 int len
= strlen(string_ptr
);
333 push_raw(len
, string_ptr
);
334 } else push_int((RInt
)0);
339 * @return the string allocated with new[], must be freed by the caller
341 char *Text_Buf::pull_string()
343 int len
= pull_int().get_val();
345 TTCN_error("Text decoder: Negative string length (%d).", len
);
346 char *string_ptr
= new char[len
+ 1];
347 pull_raw(len
, string_ptr
);
348 string_ptr
[len
] = '\0';
353 void Text_Buf::push_qualified_name(const qualified_name
& name
)
355 push_string(name
.module_name
);
356 push_string(name
.definition_name
);
359 /// Extract two strings
360 void Text_Buf::pull_qualified_name(qualified_name
& name
)
362 name
.module_name
= pull_string();
363 if (name
.module_name
[0] == '\0') {
364 delete [] name
.module_name
;
365 name
.module_name
= NULL
;
367 name
.definition_name
= pull_string();
368 if (name
.definition_name
[0] == '\0') {
369 delete [] name
.definition_name
;
370 name
.definition_name
= NULL
;
374 /** Calculate the length of the buffer and write it at the beginning.
377 void Text_Buf::calculate_length()
379 unsigned int value
= buf_len
;
380 unsigned int bytes_needed
= 1;
381 for (unsigned int tmp
= value
>> 6; tmp
!= 0; tmp
>>= 7) bytes_needed
++;
382 if ((unsigned int)buf_begin
< bytes_needed
)
383 TTCN_error("Text encoder: There is not enough space to calculate message "
385 unsigned char *buf
= (unsigned char*)data_ptr
+ buf_begin
- bytes_needed
;
386 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
388 buf
[i
] = value
& 0x7F;
390 } else buf
[i
] = value
& 0x3F;
391 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
394 buf_begin
-= bytes_needed
;
395 buf_len
+= bytes_needed
;
399 void Text_Buf::get_end(char*& end_ptr
, int& end_len
)
401 int buf_end
= buf_begin
+ buf_len
;
402 if (buf_size
- buf_end
< BUF_SIZE
) Reallocate(buf_len
+ BUF_SIZE
);
403 end_ptr
= (char*)data_ptr
+ buf_end
;
404 end_len
= buf_size
- buf_end
;
407 void Text_Buf::increase_length(int add_len
)
409 if (add_len
< 0) TTCN_error("Text decoder: Addition is negative (%d) when "
410 "increasing length.", add_len
);
411 if (buf_begin
+ buf_len
+ add_len
> buf_size
)
412 TTCN_error("Text decoder: Addition is too big when increasing length.");
416 /** Check if a known message is in the buffer
418 * @return TRUE if an int followed by the number of bytes specified
419 * by that int is in the buffer; FALSE otherwise.
420 * @post buf_pos == buf_begin
422 boolean
Text_Buf::is_message()
426 boolean ret_val
= FALSE
;
427 if (safe_pull_int(msg_len
)) {
429 char *tmp_str
= msg_len
.as_string();
430 TTCN_error("Text decoder: Negative message length (%s).", tmp_str
);
431 Free(tmp_str
); // ???
433 ret_val
= buf_pos
+ msg_len
.get_val() <= buf_begin
+ buf_len
;
439 /** Overwrite the extracted message with the rest of the buffer
440 * @post buf_pos == buf_begin
442 void Text_Buf::cut_message()
445 int msg_len
= pull_int().get_val();
446 int msg_end
= buf_pos
+ msg_len
;
447 buf_len
-= msg_end
- buf_begin
;
448 memmove((char*)data_ptr
+ buf_begin
, (char*)data_ptr
+ msg_end
,
This page took 0.040494 seconds and 5 git commands to generate.