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 /** Extract a fixed number of bytes from the buffer.
296 * @param len number of bytes to read
297 * @param data pointer to the data
298 * @pre at least \a len bytes are available, else dynamic testcase error
300 void Text_Buf::pull_raw(int len
, void *data
)
302 if (len
< 0) TTCN_error("Text decoder: Decoding raw data with negative "
303 "length (%d).", len
);
304 if (buf_pos
+ len
> buf_begin
+ buf_len
)
305 TTCN_error("Text decoder: End of buffer reached.");
306 memcpy(data
, (char*)data_ptr
+ buf_pos
, len
);
310 /** Write a 0-terminated string
312 * Writes the length followed by the raw bytes (no end marker)
314 * @param string_ptr pointer to the string
316 void Text_Buf::push_string(const char *string_ptr
)
318 if (string_ptr
!= NULL
) {
319 int len
= strlen(string_ptr
);
321 push_raw(len
, string_ptr
);
322 } else push_int((RInt
)0);
327 * @return the string allocated with new[], must be freed by the caller
329 char *Text_Buf::pull_string()
331 int len
= pull_int().get_val();
333 TTCN_error("Text decoder: Negative string length (%d).", len
);
334 char *string_ptr
= new char[len
+ 1];
335 pull_raw(len
, string_ptr
);
336 string_ptr
[len
] = '\0';
341 void Text_Buf::push_qualified_name(const qualified_name
& name
)
343 push_string(name
.module_name
);
344 push_string(name
.definition_name
);
347 /// Extract two strings
348 void Text_Buf::pull_qualified_name(qualified_name
& name
)
350 name
.module_name
= pull_string();
351 if (name
.module_name
[0] == '\0') {
352 delete [] name
.module_name
;
353 name
.module_name
= NULL
;
355 name
.definition_name
= pull_string();
356 if (name
.definition_name
[0] == '\0') {
357 delete [] name
.definition_name
;
358 name
.definition_name
= NULL
;
362 /** Calculate the length of the buffer and write it at the beginning.
365 void Text_Buf::calculate_length()
367 unsigned int value
= buf_len
;
368 unsigned int bytes_needed
= 1;
369 for (unsigned int tmp
= value
>> 6; tmp
!= 0; tmp
>>= 7) bytes_needed
++;
370 if ((unsigned int)buf_begin
< bytes_needed
)
371 TTCN_error("Text encoder: There is not enough space to calculate message "
373 unsigned char *buf
= (unsigned char*)data_ptr
+ buf_begin
- bytes_needed
;
374 for (unsigned int i
= bytes_needed
- 1; ; i
--) {
376 buf
[i
] = value
& 0x7F;
378 } else buf
[i
] = value
& 0x3F;
379 if (i
< bytes_needed
- 1) buf
[i
] |= 0x80;
382 buf_begin
-= bytes_needed
;
383 buf_len
+= bytes_needed
;
387 void Text_Buf::get_end(char*& end_ptr
, int& end_len
)
389 int buf_end
= buf_begin
+ buf_len
;
390 if (buf_size
- buf_end
< BUF_SIZE
) Reallocate(buf_len
+ BUF_SIZE
);
391 end_ptr
= (char*)data_ptr
+ buf_end
;
392 end_len
= buf_size
- buf_end
;
395 void Text_Buf::increase_length(int add_len
)
397 if (add_len
< 0) TTCN_error("Text decoder: Addition is negative (%d) when "
398 "increasing length.", add_len
);
399 if (buf_begin
+ buf_len
+ add_len
> buf_size
)
400 TTCN_error("Text decoder: Addition is too big when increasing length.");
404 /** Check if a known message is in the buffer
406 * @return TRUE if an int followed by the number of bytes specified
407 * by that int is in the buffer; FALSE otherwise.
408 * @post buf_pos == buf_begin
410 boolean
Text_Buf::is_message()
414 boolean ret_val
= FALSE
;
415 if (safe_pull_int(msg_len
)) {
417 char *tmp_str
= msg_len
.as_string();
418 TTCN_error("Text decoder: Negative message length (%s).", tmp_str
);
419 Free(tmp_str
); // ???
421 ret_val
= buf_pos
+ msg_len
.get_val() <= buf_begin
+ buf_len
;
427 /** Overwrite the extracted message with the rest of the buffer
428 * @post buf_pos == buf_begin
430 void Text_Buf::cut_message()
433 int msg_len
= pull_int().get_val();
434 int msg_end
= buf_pos
+ msg_len
;
435 buf_len
-= msg_end
- buf_begin
;
436 memmove((char*)data_ptr
+ buf_begin
, (char*)data_ptr
+ msg_end
,
This page took 0.038575 seconds and 5 git commands to generate.