1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
|
= Encoding and Decoding
:table-number: 2
:toc:
TITAN is equipped with several standard encoding/decoding mechanisms.
A part of these functions reside in the core library, but the type-dependent part must be generated by the Java code generator. In order to reduce the code size and compilation time, the code generation for encoding functions (separately for different encoders) can be switched off if they are not needed as described in <<5-compiling_ttcn3_and_asn1_modules.adoc#build-options, Build Options>>.
To make it easier to use the encoding features, a unified common API was developed. With help of this API the behaviour of the test executor in different error situations can be set during coding. There is also a common buffer class. The details of the above mentioned API as well as the specific features of the certain encoders are explained in the following sections.
[[the-common-API]]
== The Common API
The common API for encoders consists of three main parts:
* A dummy class named `TTCN_EncDec` which encapsulates functions regarding error handling.
* A buffer class named `TTCN_Buffer` which is used by the encoders to put data in, decoders to get data from.
* The functions needed to encode and decode values.
[[ttcn-encdec]]
=== TTCN_EncDec
`TTCN_EncDec` implements error handling functions.
==== Setting Error Behavior
There are lot of error situations during encoding and decoding. The coding functions can be told what to do if an error arises. To set the behaviour of test executor in a certain error situation the following function is to be invoked from the `TTCN_EncDec` class:
[source, subs="+quotes"]
static void set_error_behavior(final error_type p_et, final error_behavior_type p_eb);
WARNING: As error_type and error_behavior_type are enums defined in TTCN_EncDec class, they have to prefixed with the class name (that is `TTCN_EncDec.`).
An example usage:
[source, subs="+quotes"]
TTCN_EncDec.set_error_behavior(TTCN_EncDec.error_type.ET_ALL, TTCN_EncDec.error_behavior_type.EB_DEFAULT);
The possible values of `error_type` are detailed in the sections describing the different codings. Some common error types are shown in the table below:
.Common error types
[width="100%",cols="30%,70%",options="header",]
|=========================================================================================
|ET_UNDEF |Undefined/unknown error.
|ET_UNBOUND |Encoding of an unbound value.
|ET_REPR |Representation error (for example, internal representation of integral numbers).
|ET_ENC_ENUM |Encoding of an unknown enumerated value.
|ET_DEC_ENUM |Decoding of an unknown enumerated value.
|ET_INCOMPL_MSG |Decode error: incomplete message.
|ET_INVAL MSG |Decode error: invalid message.
|ET_CONSTRAINT |The value breaks some constraint.
|ET_INTERNAL |Internal error. Error behaviour cannot be set for this.
|ET_ALL |All error type. Usable only when setting error behaviour.
|ET_NONE |No error.
|=========================================================================================
The possible values of `error_behavior_type` are shown in the table below:
.Possible values of `error_behavior_t`
[cols="30%,70%"]
|=========================================================================
|EB_DEFAULT |Sets the default error behaviour for the selected error type.
|EB_ERROR |Raises an error if the selected error type occurs.
|EB_WARNING |Gives a warning message but tries to continue the operation.
|EB_IGNORE |Like warning but without the message.
|=========================================================================
==== Getting Error Behavior
There are two functions: one for getting the current setting and one for getting the default setting for a particular error situation.
[source]
----
static error_behavior_type get_error_behavior(final error_type p_et)
static error_behavior_type get_default_error_behavior(final error_type p_et)
----
The using of these functions are straightforward: giving a particular `error_type` the function returns the current or default `error_behavior_type` for that error situation, respectively.
==== Checking if an Error Occurred
The last coding-related error and its textual description can be retrieved anytime. Before using a coding function, it is advisable to clear the "last error". This can be achieved by the following method:
[source, subs="+quotes"]
static void clear_error();
After using some coding functions, it can be checked if an error occurred with this function:
[source, subs="+quotes"]
static error_type get_last_error_type();
This returns the last error, or `ET_NONE` if there was no error. The string representation of the error can be requested with the help of this:
[source, subs="+quotes"]
static String get_error_str();
WARNING: The above two functions do not clear the "last error" flag.
[[ttcn-buffer]]
=== TTCN_Buffer
TTCN Buffer objects are used to store encoded values and to communicate with the coding functions. If encoding a value, the result will be put in a buffer, from which can be get. In the other hand, to decode a value, the encoded octet string must be put in a TTCN_Buffer object, and the decoding functions get their input from that.
[source, subs="+quotes"]
void clear();
Resets the buffer, cleaning up its content, setting the pointers to the beginning of buffer.
[source, subs="+quotes"]
void rewind();
Rewinds the buffer, that is, sets its reading pointer to the beginning of the buffer.
[source, subs="+quotes"]
int get_pos();
Returns the (reading) position of the buffer.
[source, subs="+quotes"]
void set_pos(final int new_pos);
Sets the (reading) position to pos, or to the end of buffer, if `pos > get_len()`.
[source, subs="+quotes"]
int get_len();
Returns the amount of bytes in the buffer.
[source, subs="+quotes"]
char[] get_data();
Returns a copy of the buffer starting from its start. You can read out `count` bytes beginning from this address, where `count` is the value returned by the `get_len()` member function.
[source, subs="+quotes"]
int get_read_len();
Returns how many bytes are in the buffer to read.
[source, subs="+quotes"]
char[] get_read_data();
Returns a copy of the buffer starting from the read position of data. `count` bytes can be read out beginning from this address, where count is the value returned by the `get_read_len()` member function.
[source, subs="+quotes"]
void put_c(final char c);
Appends the byte `c` to the end of buffer.
[source, subs="+quotes"]
void put_s(final char[] cstr);
Writes a string of bytes to the end of buffer.
[source, subs="+quotes"]
void put_os(final TitanOctetString p_os);
Appends the content of the octet string to the buffer.
[source, subs="+quotes"]
void increase_length(final int size_incr);
Increases the size of the buffer.
[source, subs="+quotes"]
void cut();
Cuts (removes) the bytes between the beginning of the buffer and the read position. After calling this, the read position will be the beginning of buffer. As this function manipulates the internal data, pointers referencing to data inside the buffer will be invalid.
[source, subs="+quotes"]
void cut_end();
Cuts (removes) the bytes between the read position and the end of the buffer. After calling this, the read position remains unchanged (that is, it will point to the end of the truncated buffer). As this function manipulates the internal data, pointers referencing to data inside the buffer will be invalid.
=== Invoking the Coding Functions
Every type class has members like these:
[source]
----
public void encode(final TTCN_Typedescriptor p_td, final TTCN_Buffer p_buf,
final coding_type p_coding, final int flavour);
public void decode(final TTCN_Typedescriptor p_td,
final TTCN_Buffer p_buf, final coding_type p_coding, final int flavour);
----
Parameter `p_td` is a special type descriptor. Each type has its own descriptor, which contains the name of the type, and a lot of information used by the different encoding mechanisms. The names of the descriptors come from the name of the types: the appropriate type descriptor for type `XXX is XXX_descr_`.
This descriptor can be found in the generated code:
* complex types (record, set, record of, set of, arrays, etc..): generated into the body of the class representing the type.
* types for which no code is generated (for example record of integer): generated into the body of the class representing the module of the type.
* built in types (for example integer): in the body of the classes representing the type (for example TitanInteger in the runtime).
Parameter `p_buf` contains the encoded value. For details about using it, please consult the previous subsection.
Parameter `p_coding` is the desired coding mechanism. As `coding_type` is defined in `TTCN_EncDec`, its value must be prefixed with `TTCN_EncDec.`. For the time being, this parameter may have one of the following valuesfootnote:[BER, TEXT, XER and OER coding is not yet supported]:
* CT_RAW - RAW coding;
* CT_JSON - JSON coding;
The `flavour` parameter is depending on the chosen coding.
== BER
BER encoding and decoding is not yet supported on the Java side.
== RAW
You can use the encoding rules defined in the section "RAW encoder and decoder" in the link:https://gitlab.eclipse.org/eclipse/titan/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference] to encode and decode the following TTCN–3 types:
* boolean
* integer
* float
* bitstring
* octetstring
* charstring
* hexstring
* enumerated
* record
* set
* union
* record of
* set of
The compiler will produce code capable of RAW encoding/decoding for compound types if they have at least one `variant` attribute. +
When a compound type is only used internally or it is never RAW encoded/decoded then the attribute `variant` has to be omitted. +
When a type can be RAW encoded/decoded but with default specification then the empty variant specification can be used: `variant ""`.
[[error-situations-0]]
=== Error Situations
.RAW-coding errors
[width="100%",cols="30%,70%",options="",]
|============================================================================================================================================================
|ET_LEN_ERR |During encoding: Not enough length specified in FIELDLENGTH to encode the value. During decoding: the received message is shorter than expected.
|ET_SIGN_ERR |Unsigned encoding of a negative number.
|ET_FLOAT_NAN |Not a Number float value has been received.
|ET_FLOAT_TR |The float value will be truncated during double to single precision conversion.
|============================================================================================================================================================
[[api-0]]
=== API
The Java Application Programming Interface for RAW encoding and decoding is described in the following. It can be used for example in test port implementation, in external function implementation.
[[encoding-0]]
==== Encoding
[source]
----
public void encode(final TTCN_Typedescriptor p_td, final TTCN_Buffer p_buf,
final coding_type p_coding, final int flavour);
----
The parameter `p_coding` must be set to `TTCN_EncDec.CT_RAW`.
[[decoding-0]]
==== Decoding
[source]
----
public void decode(final TTCN_Typedescriptor p_td,
final TTCN_Buffer p_buf, final coding_type p_coding, final int flavour);
----
The parameter `p_coding` must be set to `TTCN_EncDec.CT_RAW`.
[[example-0]]
=== Example
Let us assume that we have a TTCN–3 module which contains a type named `ProtocolPdu`, and this module contains also two ports:
[source]
----
type port MyPort1 message
{
out ProtocolPdu;
in octetstring;
}
type port MyPort2 message
{
out octetstring;
in ProtocolPdu;
}
----
Then we can complete the port skeleton generated by the compiler as follows:
[source]
----
protected void outgoing_send(final ProtocolPdu send_par) {
final TTCN_Buffer buffer = new TTCN_Buffer();
send_par.encode(MyModule.ProtocolPdu.ProtocolPdu_descr_, buffer, TTCN_EncDec.coding_type.CT_RAW, 0);
final TitanOctetString encodedData = new TitanOctetString();
buffer.get_string(encodedData);
incoming_message(encodedData);
}
protected void outgoing_send(final TitanOctetString send_par) {
TTCN_EncDec.set_error_behavior(TTCN_EncDec.error_type.ET_ALL, TTCN_EncDec.error_behavior_type.EB_WARNING);
final TTCN_Buffer buffer = new TTCN_Buffer();
buffer.put_os(send_par);
final ProtocolPdu pdu = new ProtocolPdu();
pdu.decode(MyModule.ProtocolPdu.ProtocolPdu_descr_, buffer, TTCN_EncDec.coding_type.CT_RAW, 0);
incoming_message(pdu);
}
----
== TEXT
TEXT encoding and decoding is not yet supported on the Java side.
[[xml-encoding-xer]]
== XML Encoding (XER)
XML encoding and decoding is not yet supported on the Java side.
== JSON
The encoding rules defined in the section "JSON Encoder and Decoder" of the link:https://gitlab.eclipse.org/eclipse/titan/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference] can be used to encode and decode the following TTCN–3 types:
* anytype
* array
* bitstring
* boolean
* charstring
* enumerated
* float
* hexstring
* integer
* objid
* octetstring
* record`, set
* record of`, set of
* union
* universal charstring
* verdicttype
The rules also apply to the following ASN.1 types (if imported to a TTCN-3 module):
* ANY
* BIT STRING
* BOOLEAN
* BMPString
* CHOICE, open type (in instances of parameterized types)
* ENUMERATED
* GeneralString
* GraphicString
* IA5String
* INTEGER
* NULL
* NumericString
* OBJECT IDENTIFIER
* OCTET STRING
* PrintableString
* RELATIVE`-OID
* SEQUENCE, SET
* SEQUENCE OF, SET OF
* TeletexString
* UniversalString
* UTF8String
* VideotexString
* VisibleString
The compiler will produce code capable of JSON encoding/decoding for compound types if they have at least one JSON variant attribute or the `encode "JSON"` attribute (and, for compound types, all fields and elements of compound types also have a JSON variant attribute or the `encode "JSON"` attribute).
The encoder and the decoder work with JSON data encoded in UTF-8 (described in link:https://tools.ietf.org/html/rfc3629[UTF-8, a transformation format of ISO 10646]), stored in an object of type `TTCN_Buffer`. Although the contents of this object can be retrieved (using the overloads of the `get_string` function) as an instance of `TitanOctetString`, `TitanCharString` or `TitanUniversalCharString`, it is recommended to use only the `TitanOctetString` representation. `TitanCharString` is not recommended, because UTF-8 is an 8-bit encoding so the buffer may contain bytes with values over 127, which are not valid characters for a TTCN-3 `charstring` (which is implemented by `TitanCharString`, see <<5-mapping_ttcn3_data_types_to_c+\+_constructs.adoc#Charstring, Charstring>>). `TitanUniversalCharString` must not be used because its internal representation is not UTF-8.
[[error-situations-3]]
=== Error Situations
There are no extra error situations apart from the ones in <<the-common-API, The Common API>>.
[[api-3]]
=== API
The Application Programming Interface for JSON encoding and decoding is described in the following.
[[encoding-3]]
==== Encoding
[source]
----
void encode(final TTCN_Typedescriptor p_td, final TTCN_Buffer p_buf,
final coding_type p_coding, final int flavour) const;
----
The parameter `p_coding` must be set to `TTCN_EncDec.CT_JSON`.
[[decoding-3]]
==== Decoding
[source]
----
void decode(final TTCN_Typedescriptor p_td, final TTCN_Buffer p_buf,
final coding_type p_coding, final int flavour);
----
The parameter `p_coding` must be set to `TTCN_EncDec.CT_JSON`.
[[example-3]]
=== Example
Let us assume that we have a TTCN–3 module which contains a type named `ProtocolPdu`, and this module also contains two ports:
[source]
----
type port MyPort1 message
{
out ProtocolPdu;
in octetstring;
}
type port MyPort2 message
{
out octetstring;
in ProtocolPdu;
}
----
Then we can complete the port skeleton generated by the compiler:
[source]
----
void MyPort1.outgoing_send(final ProtocolPdu send_par)
{
final TTCN_Buffer buffer = new TTCN_Buffer();
send_par.encode(MyModule.ProtocolPdu.ProtocolPdu_descr_, buffer, TTCN_EncDec.coding_type.CT_JSON, 0);
final TitanOctetString encodedData = new TitanOctetString();
buffer.get_string(encodedData);
incoming_message(encodedData);
}
void MyPort2.outgoing_send(final TitanOctetString send_par)
{
TTCN_EncDec.set_error_behavior(TTCN_EncDec.error_type.ET_ALL, TTCN_EncDec.error_behavior_type.EB_WARNING);
final TTCN_Buffer buffer = new TTCN_Buffer();
buffer.put_os(send_par);
final ProtocolPdu pdu = new ProtocolPdu();
pdu.decode(MyModule.ProtocolPdu.ProtocolPdu_descr_, buffer, TTCN_EncDec.coding_type.CT_JSON, 0);
incoming_message(pdu);
}
----
== OER
OER encoding and decoding is not yet supported on the Java side.
|