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
15 * Szabo, Janos Zoltan – initial implementation
16 * Zalanyi, Balazs Andor
18 ******************************************************************************/
22 #include "../common/memory.h"
23 #include "../common/Quadruple.hh"
28 #include "PredefFunc.hh"
32 /** The amount of memory needed for an ustring containing n characters. */
33 #define MEMORY_SIZE(n) (sizeof(ustring_struct) + \
34 ((n) - 1) * sizeof(universal_char))
36 void ustring::init_struct(size_t n_uchars
)
39 /** This will represent the empty strings so they won't need allocated
40 * memory, this delays the memory allocation until it is really needed. */
41 static ustring_struct empty_string
= { 1, 0, { { '\0', '\0', '\0', '\0' } } };
42 val_ptr
= &empty_string
;
43 empty_string
.ref_count
++;
45 val_ptr
= (ustring_struct
*)Malloc(MEMORY_SIZE(n_uchars
));
46 val_ptr
->ref_count
= 1;
47 val_ptr
->n_uchars
= n_uchars
;
51 void ustring::enlarge_memory(size_t incr
)
53 if (incr
> max_string_len
- val_ptr
->n_uchars
)
54 FATAL_ERROR("ustring::enlarge_memory(size_t): length overflow");
55 size_t new_length
= val_ptr
->n_uchars
+ incr
;
56 if (val_ptr
->ref_count
== 1) {
57 val_ptr
= (ustring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(new_length
));
58 val_ptr
->n_uchars
= new_length
;
60 ustring_struct
*old_ptr
= val_ptr
;
62 init_struct(new_length
);
63 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
, old_ptr
->n_uchars
*
64 sizeof(universal_char
));
68 void ustring::copy_value()
70 if (val_ptr
->ref_count
> 1) {
71 ustring_struct
*old_ptr
= val_ptr
;
73 init_struct(old_ptr
->n_uchars
);
74 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
,
75 old_ptr
->n_uchars
* sizeof(universal_char
));
79 void ustring::clean_up()
81 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
82 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
83 else FATAL_ERROR("ustring::clean_up()");
86 int ustring::compare(const ustring
& s
) const
88 if (val_ptr
== s
.val_ptr
) return 0;
89 for (size_t i
= 0; ; i
++) {
90 if (i
== val_ptr
->n_uchars
) {
91 if (i
== s
.val_ptr
->n_uchars
) return 0;
93 } else if (i
== s
.val_ptr
->n_uchars
) return 1;
94 else if (val_ptr
->uchars_ptr
[i
].group
> s
.val_ptr
->uchars_ptr
[i
].group
)
96 else if (val_ptr
->uchars_ptr
[i
].group
< s
.val_ptr
->uchars_ptr
[i
].group
)
98 else if (val_ptr
->uchars_ptr
[i
].plane
> s
.val_ptr
->uchars_ptr
[i
].plane
)
100 else if (val_ptr
->uchars_ptr
[i
].plane
< s
.val_ptr
->uchars_ptr
[i
].plane
)
102 else if (val_ptr
->uchars_ptr
[i
].row
> s
.val_ptr
->uchars_ptr
[i
].row
)
104 else if (val_ptr
->uchars_ptr
[i
].row
< s
.val_ptr
->uchars_ptr
[i
].row
)
106 else if (val_ptr
->uchars_ptr
[i
].cell
> s
.val_ptr
->uchars_ptr
[i
].cell
)
108 else if (val_ptr
->uchars_ptr
[i
].cell
< s
.val_ptr
->uchars_ptr
[i
].cell
)
111 return 0; // should never get here
114 ustring::ustring(unsigned char p_group
, unsigned char p_plane
,
115 unsigned char p_row
, unsigned char p_cell
)
118 val_ptr
->uchars_ptr
[0].group
= p_group
;
119 val_ptr
->uchars_ptr
[0].plane
= p_plane
;
120 val_ptr
->uchars_ptr
[0].row
= p_row
;
121 val_ptr
->uchars_ptr
[0].cell
= p_cell
;
124 ustring::ustring(size_t n
, const universal_char
*uc_ptr
)
126 // Check for UTF8 encoding and decode it
127 // incase the editor encoded the TTCN-3 file with UTF-8
130 for (size_t i
= 0; i
< n
; ++i
) {
131 if (uc_ptr
[i
].group
!= 0 || uc_ptr
[i
].plane
!= 0 || uc_ptr
[i
].row
!= 0) {
136 octet_str
+= Common::hexdigit_to_char(uc_ptr
[i
].cell
/ 16);
137 octet_str
+= Common::hexdigit_to_char(uc_ptr
[i
].cell
% 16);
140 string
* ret
= Common::get_stringencoding(octet_str
);
141 if ("UTF-8" != *ret
) {
147 ustring s
= Common::decode_utf8(octet_str
, CharCoding::UTF_8
);
149 val_ptr
->ref_count
++;
152 memcpy(val_ptr
->uchars_ptr
, uc_ptr
, n
* sizeof(universal_char
));
156 ustring::ustring(const string
& s
)
158 // Check for UTF8 encoding and decode it
159 // incase the editor encoded the TTCN-3 file with UTF-8
162 size_t len
= s
.size();
163 for (size_t i
= 0; i
< len
; ++i
) {
164 octet_str
+= Common::hexdigit_to_char((unsigned char)(s
[i
]) / 16);
165 octet_str
+= Common::hexdigit_to_char((unsigned char)(s
[i
]) % 16);
168 string
* ret
= Common::get_stringencoding(octet_str
);
169 if ("UTF-8" != *ret
) {
175 ustring s
= Common::decode_utf8(octet_str
, CharCoding::UTF_8
);
177 val_ptr
->ref_count
++;
179 init_struct(s
.size());
180 const char *src
= s
.c_str();
181 for (size_t i
= 0; i
< val_ptr
->n_uchars
; i
++) {
182 val_ptr
->uchars_ptr
[i
].group
= 0;
183 val_ptr
->uchars_ptr
[i
].plane
= 0;
184 val_ptr
->uchars_ptr
[i
].row
= 0;
185 val_ptr
->uchars_ptr
[i
].cell
= src
[i
];
190 ustring::ustring(const char** uid
, const int n
) {
191 //Init the size for characters
193 for (size_t i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
194 const char * uidchar
= uid
[i
];
195 size_t offset
= 1; //Always starts with u or U
196 offset
= uidchar
[1] == '+' ? offset
+ 1 : offset
; //Optional '+'
197 string chunk
= string(uidchar
+ offset
);
198 //Convert hex to int and get value
199 Common::int_val_t
* val
= Common::hex2int(chunk
);
200 Common::Int int_val
= val
->get_val();
202 //Fill in the quadruple
203 val_ptr
->uchars_ptr
[i
].group
= (int_val
>> 24) & 0xFF;
204 val_ptr
->uchars_ptr
[i
].plane
= (int_val
>> 16) & 0xFF;
205 val_ptr
->uchars_ptr
[i
].row
= (int_val
>> 8) & 0xFF;
206 val_ptr
->uchars_ptr
[i
].cell
= int_val
& 0xFF;
213 void ustring::clear()
215 if (val_ptr
->n_uchars
> 0) {
221 ustring
ustring::substr(size_t pos
, size_t n
) const
223 if (pos
> val_ptr
->n_uchars
)
224 FATAL_ERROR("ustring::substr(size_t, size_t): position is outside of string");
225 if (pos
== 0 && n
>= val_ptr
->n_uchars
) return *this;
226 if (n
> val_ptr
->n_uchars
- pos
) n
= val_ptr
->n_uchars
- pos
;
227 return ustring(n
, val_ptr
->uchars_ptr
+ pos
);
230 void ustring::replace(size_t pos
, size_t n
, const ustring
& s
)
232 if (pos
> val_ptr
->n_uchars
)
233 FATAL_ERROR("ustring::replace(): start position is outside the string");
234 if (pos
+ n
> val_ptr
->n_uchars
)
235 FATAL_ERROR("ustring::replace(): end position is outside the string");
236 size_t s_len
= s
.size();
237 /* The replacement string is greater than the maximum string length. The
238 replaced characters are taken into account. */
239 if (s_len
> max_string_len
- val_ptr
->n_uchars
+ n
)
240 FATAL_ERROR("ustring::replace(): length overflow");
241 size_t new_size
= val_ptr
->n_uchars
- n
+ s_len
;
246 ustring_struct
*old_ptr
= val_ptr
;
247 old_ptr
->ref_count
--;
248 init_struct(new_size
);
249 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
,
250 pos
* sizeof(universal_char
));
251 memcpy(val_ptr
->uchars_ptr
+ pos
, s
.u_str(),
252 s_len
* sizeof(universal_char
));
253 memcpy(val_ptr
->uchars_ptr
+ pos
+ s_len
, old_ptr
->uchars_ptr
+ pos
+ n
,
254 (old_ptr
->n_uchars
- pos
- n
) * sizeof(universal_char
));
255 if (old_ptr
->ref_count
== 0) Free(old_ptr
);
259 string
ustring::get_stringRepr() const
262 enum { INIT
, PCHAR
, UCHAR
} state
= INIT
;
263 for (size_t i
= 0; i
< val_ptr
->n_uchars
; i
++) {
264 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
265 if (uchar
.group
== 0 && uchar
.plane
== 0 && uchar
.row
== 0 &&
266 string::is_printable(uchar
.cell
)) {
267 // the actual character is printable
269 case UCHAR
: // concatenation sign if previous part was not printable
272 case INIT
: // opening "
275 case PCHAR
: // the character itself
276 ret_val
.append_stringRepr(uchar
.cell
);
281 // the actual character is not printable
283 case PCHAR
: // closing " if previous part was printable
286 case UCHAR
: // concatenation sign
289 case INIT
: // the character itself in quadruple notation
291 ret_val
+= Common::Int2string(uchar
.group
);
293 ret_val
+= Common::Int2string(uchar
.plane
);
295 ret_val
+= Common::Int2string(uchar
.row
);
297 ret_val
+= Common::Int2string(uchar
.cell
);
306 case INIT
: // the string was empty
309 case PCHAR
: // last character was printable -> closing "
318 string
ustring::get_stringRepr_for_pattern() const {
319 string ret_val
; // empty string
320 for (size_t i
= 0; i
< val_ptr
->n_uchars
; i
++) {
321 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
322 if (uchar
.group
== 0 && uchar
.plane
== 0 && uchar
.row
== 0 &&
323 string::is_printable(uchar
.cell
)) {
324 ret_val
.append_stringRepr(uchar
.cell
);
327 ret_val
+= Common::Int2string(uchar
.group
);
329 ret_val
+= Common::Int2string(uchar
.plane
);
331 ret_val
+= Common::Int2string(uchar
.row
);
333 ret_val
+= Common::Int2string(uchar
.cell
);
340 char* ustring::convert_to_regexp_form() const {
341 char* res
= (char*)Malloc(val_ptr
->n_uchars
* 8 + 1);
343 res
[val_ptr
->n_uchars
* 8] = '\0';
345 for (size_t i
= 0; i
< val_ptr
->n_uchars
; i
++, ptr
+= 8) {
346 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
347 q
.set(uchar
.group
, uchar
.plane
, uchar
.row
, uchar
.cell
);
348 Quad::get_hexrepr(q
, ptr
);
353 ustring
& ustring::operator=(const ustring
& s
)
358 val_ptr
->ref_count
++;
363 ustring::universal_char
& ustring::operator[](size_t n
)
365 if (n
>= val_ptr
->n_uchars
)
366 FATAL_ERROR("ustring::operator[](size_t): position is outside the string");
368 return val_ptr
->uchars_ptr
[n
];
371 const ustring::universal_char
& ustring::operator[](size_t n
) const
373 if (n
>= val_ptr
->n_uchars
)
374 FATAL_ERROR("ustring::operator[](size_t) const: position is outside the string");
375 return val_ptr
->uchars_ptr
[n
];
378 ustring
ustring::operator+(const string
& s2
) const
380 size_t s2_size
= s2
.size();
381 if (s2_size
> max_string_len
- val_ptr
->n_uchars
)
382 FATAL_ERROR("ustring::operator+(const string&): length overflow");
384 ustring
s(val_ptr
->n_uchars
+ s2_size
);
385 memcpy(s
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
*
386 sizeof(universal_char
));
387 const char *src
= s2
.c_str();
388 for (size_t i
= 0; i
< s2_size
; i
++) {
389 s
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].group
= 0;
390 s
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].plane
= 0;
391 s
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].row
= 0;
392 s
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].cell
= src
[i
];
398 ustring
ustring::operator+(const ustring
& s2
) const
400 if (s2
.val_ptr
->n_uchars
> max_string_len
- val_ptr
->n_uchars
)
401 FATAL_ERROR("ustring::operator+(const ustring&): length overflow");
402 if (val_ptr
->n_uchars
== 0) return s2
;
403 else if (s2
.val_ptr
->n_uchars
== 0) return *this;
405 ustring
s(val_ptr
->n_uchars
+ s2
.val_ptr
->n_uchars
);
406 memcpy(s
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
*
407 sizeof(universal_char
));
408 memcpy(s
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
,
409 s2
.val_ptr
->uchars_ptr
, s2
.val_ptr
->n_uchars
* sizeof(universal_char
));
414 ustring
& ustring::operator+=(const string
& s
)
416 size_t s_size
= s
.size();
418 size_t old_size
= val_ptr
->n_uchars
;
419 enlarge_memory(s_size
);
420 const char *src
= s
.c_str();
421 for (size_t i
= 0; i
< s_size
; i
++) {
422 val_ptr
->uchars_ptr
[old_size
+ i
].group
= 0;
423 val_ptr
->uchars_ptr
[old_size
+ i
].plane
= 0;
424 val_ptr
->uchars_ptr
[old_size
+ i
].row
= 0;
425 val_ptr
->uchars_ptr
[old_size
+ i
].cell
= src
[i
];
431 ustring
& ustring::operator+=(const ustring
& s
)
433 if (s
.val_ptr
->n_uchars
> 0) {
434 if (val_ptr
->n_uchars
> 0) {
435 size_t old_size
= val_ptr
->n_uchars
, s_size
= s
.val_ptr
->n_uchars
;
436 enlarge_memory(s_size
);
437 memcpy(val_ptr
->uchars_ptr
+ old_size
, s
.val_ptr
->uchars_ptr
,
438 s_size
* sizeof(universal_char
));
442 val_ptr
->ref_count
++;
448 bool ustring::operator==(const ustring
& s2
) const
450 if (val_ptr
== s2
.val_ptr
) return true;
451 else if (val_ptr
->n_uchars
!= s2
.val_ptr
->n_uchars
) return false;
452 else return !memcmp(val_ptr
->uchars_ptr
, s2
.val_ptr
->uchars_ptr
,
453 val_ptr
->n_uchars
* sizeof(universal_char
));
456 bool operator==(const ustring::universal_char
& uc1
,
457 const ustring::universal_char
& uc2
)
459 return uc1
.group
== uc2
.group
&& uc1
.plane
== uc2
.plane
&&
460 uc1
.row
== uc2
.row
&& uc1
.cell
== uc2
.cell
;
463 bool operator<(const ustring::universal_char
& uc1
,
464 const ustring::universal_char
& uc2
)
466 if (uc1
.group
< uc2
.group
) return true;
467 else if (uc1
.group
> uc2
.group
) return false;
468 else if (uc1
.plane
< uc2
.plane
) return true;
469 else if (uc1
.plane
> uc2
.plane
) return false;
470 else if (uc1
.row
< uc2
.row
) return true;
471 else if (uc1
.row
> uc2
.row
) return false;
472 else return uc1
.cell
< uc2
.cell
;
475 string
ustring_to_uft8(const ustring
& ustr
)
478 for(size_t i
= 0; i
< ustr
.size(); i
++) {
479 unsigned char g
= ustr
[i
].group
;
480 unsigned char p
= ustr
[i
].plane
;
481 unsigned char r
= ustr
[i
].row
;
482 unsigned char c
= ustr
[i
].cell
;
483 if(g
== 0x00 && p
<= 0x1F) {
485 if(r
== 0x00 && c
<= 0x7F) {
491 ret_val
+= (0xC0 | r
<< 2 | c
>> 6);
492 ret_val
+= (0x80 | (c
& 0x3F));
496 ret_val
+= (0xE0 | r
>> 4);
497 ret_val
+= (0x80 | (r
<< 2 & 0x3C) | c
>> 6);
498 ret_val
+= (0x80 | (c
& 0x3F));
503 ret_val
+= (0xF0 | p
>> 2);
504 ret_val
+= (0x80 | (p
<< 4 & 0x30) | r
>> 4);
505 ret_val
+= (0x80 | (r
<< 2 & 0x3C) | c
>> 6);
506 ret_val
+= (0x80 | (c
& 0x3F));
511 ret_val
+= (0xF8 | g
);
512 ret_val
+= (0x80 | p
>> 2);
513 ret_val
+= (0x80 | (p
<< 4 & 0x30) | r
>> 4);
514 ret_val
+= (0x80 | (r
<< 2 & 0x3C) | c
>> 6);
515 ret_val
+= (0x80 | (c
& 0x3F));
519 ret_val
+= (0xFC | g
>> 6);
520 ret_val
+= (0x80 | (g
& 0x3F));
521 ret_val
+= (0x80 | p
>> 2);
522 ret_val
+= (0x80 | (p
<< 4 & 0x30) | r
>> 4);
523 ret_val
+= (0x80 | (r
<< 2 & 0x3C) | c
>> 6);
524 ret_val
+= (0x80 | (c
& 0x3F));