debugger: added help in single mode UI, plus minor fixes
[deliverable/titan.core.git] / core / Textbuf.cc
CommitLineData
d44e3c4f 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
7 *
8 * Contributors:
9 * Balasko, Jeno
10 * Forstner, Matyas
11 * Kovacs, Ferenc
12 * Raduly, Csaba
13 * Szabo, Janos Zoltan – initial implementation
14 * Szalai, Gabor
15 *
16 ******************************************************************************/
970ed795
EL
17#include <stdio.h>
18#include <stdlib.h> // for atof
19#include <string.h>
20#include <errno.h>
21
22#include "Textbuf.hh"
23#include "../common/memory.h"
24#include "Error.hh"
25
26#include <openssl/bn.h>
27
28// Note: Do not use dbgnew.hh; it doesn't play well with Qt in mctr_gui
29
30#define BUF_SIZE 1000
31#define BUF_HEAD 24
32
33
34Text_Buf::Text_Buf()
35: buf_size()
36, buf_begin(BUF_HEAD)
37, buf_pos(BUF_HEAD)
38, buf_len(0)
39{
40 Allocate(BUF_SIZE);
41}
42
43Text_Buf::~Text_Buf()
44{
45 Free(data_ptr);
46}
47
48void Text_Buf::Allocate(int size)
49{
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
54}
55
56void Text_Buf::Reallocate(int size)
57{
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
63 }
64}
65
66void Text_Buf::reset()
67{
68 buf_begin = BUF_HEAD;
69 Reallocate(BUF_SIZE);
70 buf_pos = BUF_HEAD;
71 buf_len = 0;
72}
73
74/** Encode a native integer in the buffer
75 *
76 * @param value native integer
77 */
78void Text_Buf::push_int(const RInt& value)
79{
80 int_val_t tmp(value);
81 push_int(tmp);
82}
83
84/** Encode an integer (may be bigint) into the text buffer
85 *
86 * @param value may be big integer
87 */
88void Text_Buf::push_int(const int_val_t& value)
89{
90 if (value.is_native()) {
91 boolean is_negative = value < 0;
92 unsigned int unsigned_value = is_negative ? -value.get_val() :
93 value.get_val();
94 unsigned int bytes_needed = 1;
95 for (unsigned int tmp = unsigned_value >> 6; tmp != 0; tmp >>= 7)
96 bytes_needed++;
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.
103 if (i > 0) {
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;
109 if (i == 0) break;
110 }
111 if (is_negative) buf[0] |= 0x40; // Put in the sign bit
112 buf_len += bytes_needed;
113 } else {
114 BIGNUM *D = BN_new();
115 BN_copy(D, value.get_val_openssl());
116 unsigned num_bits = BN_num_bits(D);
117 // Calculation
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 =>
123 // (num_bits+7)/7 =>
124 // (num_bits / 7)+1
125
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
131 if (i > 0) {
132 buf[i] = D->d[0] & 0x7f;
133 if (!BN_rshift(D, D, 7)) return;
134 } else {
135 buf[i] = (D->top ? D->d[0] : 0) & 0x3f;
136 }
137 if (i < num_bytes - 1) buf[i] |= 0x80;
138 if (i == 0) break;
139 }
140 if (BN_is_negative(D)) buf[0] |= 0x40; // Put in the sign bit
141 BN_free(D);
142 buf_len += num_bytes;
143 }
144}
145
146/** Extract an integer from the buffer.
147 *
148 * @return the extracted value
149 * @pre An integer must be available, else dynamic testcase error
150 */
151const int_val_t Text_Buf::pull_int()
152{
153 int_val_t value;
154 if (!safe_pull_int(value))
155 TTCN_error("Text decoder: Decoding of integer failed.");
156 return value;
157}
158
159/** Extract an integer if it's safe to do so.
160 *
161 * @param[out] value set to the extracted value if successful
162 * @return TRUE if an integer could be extracted, FALSE otherwise
163 */
164boolean Text_Buf::safe_pull_int(int_val_t& value)
165{
166 int buf_end = buf_begin + buf_len;
167 if (buf_pos >= buf_end) return FALSE;
168 int pos = buf_pos;
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();
176 int neg = 0;
177 BN_clear(D);
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)
183 BN_lshift(D, D, 7);
184 }
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);
188 } else {
189 value = int_val_t(neg ? -D->d[0] : D->d[0]);
190 BN_free(D);
191 }
192 } else {
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;
198 }
199 if (buf[0] & 0x40) value = -loc_value;
200 else value = loc_value;
201 }
202 buf_pos = pos + 1;
203 return TRUE;
204}
205
206/** Encode a double precision floating point number in the buffer.
207 *
208 * @param value
209 */
210void Text_Buf::push_double(double value)
211{
3abe9331 212 Reallocate(buf_len + 8);
213 union{
214 double d;
215 unsigned char c[8];
216 } m;
217 m.d=value;
218 unsigned char *st=(unsigned char *)data_ptr + buf_begin + buf_len;
219#if defined __sparc__ || defined __sparc
220 st[0]=m.c[0];
221 st[1]=m.c[1];
222 st[2]=m.c[2];
223 st[3]=m.c[3];
224 st[4]=m.c[4];
225 st[5]=m.c[5];
226 st[6]=m.c[6];
227 st[7]=m.c[7];
228#else
229 st[0]=m.c[7];
230 st[1]=m.c[6];
231 st[2]=m.c[5];
232 st[3]=m.c[4];
233 st[4]=m.c[3];
234 st[5]=m.c[2];
235 st[6]=m.c[1];
236 st[7]=m.c[0];
237#endif
238 buf_len += 8;
970ed795
EL
239}
240
241/** Extract a double precision floating point number
242 *
243 * @return the extracted value
244 * @pre A suitably formatted float value must be in the buffer, else
245 * dynamic testcase error
246 */
247double Text_Buf::pull_double()
248{
3abe9331 249 if (buf_pos + 8 > buf_begin + buf_len) TTCN_error("Text decoder: Decoding of float failed. "
970ed795 250 "(End of buffer reached)");
3abe9331 251 const unsigned char *st = (unsigned char *)data_ptr+buf_pos;
252
253 union{
254 double d;
255 unsigned char c[8];
256 } m;
257#if defined __sparc__ || defined __sparc
258 m.c[0]=st[0];
259 m.c[1]=st[1];
260 m.c[2]=st[2];
261 m.c[3]=st[3];
262 m.c[4]=st[4];
263 m.c[5]=st[5];
264 m.c[6]=st[6];
265 m.c[7]=st[7];
266#else
267 m.c[0]=st[7];
268 m.c[1]=st[6];
269 m.c[2]=st[5];
270 m.c[3]=st[4];
271 m.c[4]=st[3];
272 m.c[5]=st[2];
273 m.c[6]=st[1];
274 m.c[7]=st[0];
275#endif
276buf_pos += 8;
277return m.d;
970ed795
EL
278}
279
280/** Write a fixed number of bytes in the buffer.
281 *
282 * @param len number of bytes to write
283 * @param data pointer to the data
284 */
285void Text_Buf::push_raw(int len, const void *data)
286{
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);
291 buf_len += len;
292}
293
016a1a93
BB
294void Text_Buf::push_raw_front(int len, const void* data)
295{
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];
301 }
302 memcpy((char*)data_ptr + buf_begin, data, len);
303 buf_len += len;
304}
305
970ed795
EL
306/** Extract a fixed number of bytes from the buffer.
307 *
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
311 */
312void Text_Buf::pull_raw(int len, void *data)
313{
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);
319 buf_pos += len;
320}
321
322/** Write a 0-terminated string
323 *
324 * Writes the length followed by the raw bytes (no end marker)
325 *
326 * @param string_ptr pointer to the string
327 */
328void Text_Buf::push_string(const char *string_ptr)
329{
330 if (string_ptr != NULL) {
331 int len = strlen(string_ptr);
332 push_int(len);
333 push_raw(len, string_ptr);
334 } else push_int((RInt)0);
335}
336
337/** Extract a string
338 *
339 * @return the string allocated with new[], must be freed by the caller
340 */
341char *Text_Buf::pull_string()
342{
343 int len = pull_int().get_val();
344 if (len < 0)
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';
349 return string_ptr;
350}
351
352/// Push two strings
353void Text_Buf::push_qualified_name(const qualified_name& name)
354{
355 push_string(name.module_name);
356 push_string(name.definition_name);
357}
358
359/// Extract two strings
360void Text_Buf::pull_qualified_name(qualified_name& name)
361{
362 name.module_name = pull_string();
363 if (name.module_name[0] == '\0') {
364 delete [] name.module_name;
365 name.module_name = NULL;
366 }
367 name.definition_name = pull_string();
368 if (name.definition_name[0] == '\0') {
369 delete [] name.definition_name;
370 name.definition_name = NULL;
371 }
372}
373
374/** Calculate the length of the buffer and write it at the beginning.
375 *
376 */
377void Text_Buf::calculate_length()
378{
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 "
384 "length.");
385 unsigned char *buf = (unsigned char*)data_ptr + buf_begin - bytes_needed;
386 for (unsigned int i = bytes_needed - 1; ; i--) {
387 if (i > 0) {
388 buf[i] = value & 0x7F;
389 value >>= 7;
390 } else buf[i] = value & 0x3F;
391 if (i < bytes_needed - 1) buf[i] |= 0x80;
392 if (i == 0) break;
393 }
394 buf_begin -= bytes_needed;
395 buf_len += bytes_needed;
396}
397
398
399void Text_Buf::get_end(char*& end_ptr, int& end_len)
400{
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;
405}
406
407void Text_Buf::increase_length(int add_len)
408{
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.");
413 buf_len += add_len;
414}
415
416/** Check if a known message is in the buffer
417 *
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
421 */
422boolean Text_Buf::is_message()
423{
424 rewind();
425 int_val_t msg_len;
426 boolean ret_val = FALSE;
427 if (safe_pull_int(msg_len)) {
428 if (msg_len < 0) {
429 char *tmp_str = msg_len.as_string();
430 TTCN_error("Text decoder: Negative message length (%s).", tmp_str);
431 Free(tmp_str); // ???
432 }
433 ret_val = buf_pos + msg_len.get_val() <= buf_begin + buf_len;
434 }
435 rewind();
436 return ret_val;
437}
438
439/** Overwrite the extracted message with the rest of the buffer
440 * @post buf_pos == buf_begin
441 */
442void Text_Buf::cut_message()
443{
444 if (is_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,
449 buf_len);
450 Reallocate(buf_len);
451 rewind();
452 }
453}
This page took 0.041708 seconds and 5 git commands to generate.