IBM
Contents Index Previous Next



EGci Value Construction and Functions


The GCI interface has been defined as a base for executable test suite adaptation. One part of this interface covers values, how to build them, access them, etc. While this interface was not enough, a set of functions has been added with the EGci prefix so that the GCI functions (a set defined by a standard) was not changed. The purpose of this section is to describe this paradigm of value construction and the current EGci functions available.

Value Construction

The major difference in value handling is how values are constructed. Values are either created by the GciMk-prefixed functions, followed by a GciSetType call, or value are created by a call to the EGciMkValue function. The run time system is compatible with both alternatives but the latter is preferred. The difference is that the GciMk-function creates untyped values of a given predefined type (SEQUENCE, SET, INTEGER, etc.) while the EGciMkValue takes the type descriptor of the user-defined type and creates the complete value structure with correct types throughout the whole value structure. Values of type SEQUENCE OF, SET OF and CHOICE cannot be fully instatiated since the size/choice of the value is not known at code generation time. Elements of the SEQUENCE/SET type are appended explicitly and CHOICE values are also selected explicitly.

The procedure is to create the value structure (with uninitialized leaf values) and then extract the proper value (container) through ordinary field access and extraction functions. Then the value is assigned using the EGciAssign function. When available, for simple non-structured values, EGciSet/GciSet-functions can also be used on the extracted values.

Below you will find two alternatives for creating a value given the following type:

T ::= SEQUENCE 
{ 
  a SEQUENCE { 
     b MyINTEGER 
  }, 
  c MyINTEGER 
}

MyINTEGER ::= INTEGER

v T := { a { b 17 }, c 42 }

Alternative 1 - Using GciMkSEQUENCE and GciSetType

The individual values through out the structured value have to be created and the correct type set. It is also impossible to set the correct type for the inlined types since they are unknown.

...
value = GciMkSEQUENCE(1);
GciSetType(value, GcTD);

inner_seq = GciMkSEQUENCE(1);
/* GciSetType(inner_seq, ?); This is not possible 
since the inlined type is not available to the user. 
A generated no-name type exists but is not known. So 
the SEQUENCE will be untyped (only a SEQUENCE). This 
is not a problem with alternative 2. */

b = GciMkINTEGER(17);
GciSetType(b, GcMyINTEGERD);
GciSetField(inner_sequence, 1, b);
c = GciMkINTEGER(42);
GciSetType(c, GcMyINTEGERD);
GciSetField(value, 1, inner_seq);
GciSetField(value, 2, c);
...

Alternative 2 - Using EGciMkValue (Recommended Approach)

Using the EGciMkValue function makes it somewhat more readable, but what is more important is that the final value has the correct type throughout the structure (all done by the generated type information used in the call to EGciMkValue). All field names are also correct.

...
value = EGciMkValue(GcTD); 
/* With this call the whole structure is created and 
the basic leaf values are only extracted and set 
("filled in"). */

tmp = GciGetField(value, 1);
tmp = GciGetField(tmp, 1);
EGciSetINTEGER(tmp, 17);

tmp = GciGetField(value, 2);
EGciSetINTEGER(tmp, 42);
...

Available Functions

GciValue * EGciMkValue(int)

Takes the generated type identifier constant Gc<type>D and creates a proper value using all available type information generated. This function is faster than the EGciMkValueFromTypeName but the type identifier constants can potentially change their numeric value if new types are added to the test suite. Any depending encoder/decoders have to be recompiled if the generated type information changes. If generation dependent information is required, the EGciMkValueFromTypeName should be used.

Example 292

Given the type MyType, the call for constructing a value would be EGciMkValue(GcMyTypeD).

GciValue * EGciMkValueFromTypeName(const char* tname)

Same as EGciMkValue but it takes the (bare) name of the type.

Example 293

Given the type MyType the call for constructing a value would be EGciMkValueFromTypeName("MyType").

void EGciRmValue(GciValue *value)

This function deletes a constructed value.

GciStatus EGciAssign(GciValue *destination, GciValue *source)

Given the two values, which must be instantiated values of the same type, the source is assigned to the destination value.

GciValue * EGciGetFieldByName(GciValue *val, const char* name)

This function returns the named member of a SEQUENCE, SET or CHOICE value. If the value given by the parameter val has no member with the name given by the parameter name, the return value is NULL. Note that the return value is not a copy of the value member, so if any operations are applied to the return value, this will directly effect the member value.

GciStatus EGciSetMemberByName(GciValue *val, const char* name, GciValue *mem_val)

Sets the named member of a SEQUENCE, SET or CHOICE value to the given value (mem_value). This is the same as doing an extraction followed by an assignment.

GciStatus EGciSetEmptySET_OF(GciValue *value)

Sets the value to the defined state. That is, it is an empty SET OF value.

GciStatus EGciSetEmptySEQUENCE_OF(GciValue *value)

Sets the value to the defined state. That is, it is an empty SEQUENCE OF value.

GciStatus EGciSetOMIT(GciValue *value)

Sets the given optional value as omitted.

GciStatus EGciSetBOOLEAN(GciValue *value, Bool v)

Sets a constructed value of the (base) type BOOLEAN to the given boolean value.

GciStatus EGciSetSTRING(GciValue *value, const char *)

Sets a constructed value of any string base type (BITSTRING, OCTETSTRING, IA5String, etc.) to the given string value.

GciStatus EGciSetINTEGER(GciValue *value, int number)

This function sets a constructed value of the (base) type INTEGER to the value given by the number parameter. This function may be used for INTEGER values in the range of -2^31..2^31-1. The function EGciSetBigINTEGER is more universal and is used for unlimited INTEGER values.

Note:

In the TTCN Suite RTS there is support for INTEGER values in the range of:
-2^32-1..2^32-1

GciStatus EGciSetBigINTEGER(GciValue *value, const char *number)

This function sets a constructed value of the (base) type INTEGER to the given integer value.
This function should be used instead of EGciSetINTEGER when the value is unknown or larger than what is allowed for the type int.

GciStatus EGciSetNULL(GciValue *value)

This function sets a constructed value of the (base) type NULL to a NULL value.

GciValue * EGciSetENUMERATEDByName(GciValue *val, const char* enum_name)

This function sets the actual value of the ENUMERATED value to one of its declared named numbers. For example, EGciSetENUMERATEDByName(gcivalue, "foo"), where "foo" is one of the named numbers in the type.

Example 294

EType ::= ENUMERATED { first, second, third }

GciValue *eval = EGciMkValue(GcETypeD);
EGciSetENUMERATEDByName(eval, "second");


const char * EGciGetENUMERATEDName(GciValue *value)

Retrieves the name of the current value.

Example 295

Continuing Example 294, a call to EGciGetENUMERATEDName(eval) would return the string "second".

GciValue * EGciGetChoiceMemberByName(GciValue *value, const char *name)

CHOICE values are not constructed all the way down to its leaf value since the information about the selected field is not available in the type information. When this function is called, the value construction is continued and proper value will be constructed for the selected CHOICE field (name) and the value can then be assigned properly.

GciValue * EGciGetChoiceMemberByTag(GciValue *value, GciTagClass tag_class, int tag)

Equivalent to EGciGetChoiceMemberByName but the unique tag of the choice element instead of the name is used.

GciValue * EGciGetSEQUENCE_OFElement(GciValue *value)

Constructs a new value given the underlying/contained type of the SEQUENCE_OF type. The newly constructed value must be appended using the GciAddElem function.

GciValue * EGciGetSET_OFElement(GciValue *value)

Constructs a new value given the underlying/contained type of the SET_OF type. The newly constructed value must be appended using the GciAddElem function.

Bool EGciGetAnyValue(GciValue *value)

Predicate to check if the value is ANY value attribute. Note that this has nothing to do with the GciGetANY function since that function operates on values of the type ANY.

Bool EGciGetAnyOrOmit(GciValue *value)

Predicate to check if the value is ANYOROMIT value attribute.

Bool EGciGetIfPresent(GciValue *value)

Predicate to check if the IF_PRESENT value attribute is specified for this value.

Bool EGciGetDefault(GciValue *value)

Predicate to check if the instatiated value comes from the default value of the type or not.

Error Handling

If an error occurs during execution, the error state is propagated up through the call stack and error information is added. An error has occurred when either the EGciGetErrorCount function returns a number greater than zero or a Gci/EGci-function call has returned GciNotOk. The error message is retrieved by EGciGetLastErrorMessage and reset by EGciClearError.

unsigned int EGciGetErrorCount()

Retrieve the current number of errors detected by the run time system.

const char* EGciGetLastErrorMessage(void)

Retrieve the last error message in text form.

void EGciClearError()

Clear the error state of the run time system.

Miscellaneous

void EGciDumpValue(FILE *stream, const char *prefix, GciValue *value, const char *suffix)

Prints the given value on stream. The prefix and suffix are printed before and after the value dump respectively.

int EGciDumpValueInBuffer(char* buffer, int maxlen, GciValue* value);

Returns 0 when value was successfully dumped into buffer. If the function fails it returns the required buffer size for a successful dump of value.
This function can be used for printing a value from the code, for example a value in a GciValue structure to be printed in a file. Call EGciDumpValueInBuffer with a large enough buffer (possibly first check the necessary buffer size), then print the value from buffer.

void EGciSetDebugStream(FILE *stream)

Set the debug stream where logging will be made. It is set to stderr by default.

Examples


MyString         ::= IA5String
EmailAddress     ::= MyString
SnailmailAddress ::= SET { street MyString, number INTEGER }
AddressKind      ::= ENUMERATED { email, snailmail }

-- This represents a contact with name and an address. 

Contact ::= SEQUENCE {
  name MyString,
  address_kind AddressKind
  address CHOICE {
    email     EmailAddress, 
    snailmail SnailmailAddress
  }
}

A value would be constructed in the following way:

GciValue *tmp;
GciValue *address;
CciValue *contact;

contact = EGciMkValue( GcContactD);

tmp = EGciGetFieldByName(contact, "name");
EGciSetSTRING(tmp, "Elvis");

tmp = EGciGetFieldByName(contact, "address_kind");
EGciSetENUMERATEDByName(tmp, "snailmail");

 address = EGciGetFieldByName(contact, "address");
 address = EGciGetChoiceMemberByName(address, "snailmail");
 tmp = EGciGetFieldByName(address, "street");
 EGciSetSTRING(tmp, "High road");
 tmp = EGciGetFieldByName(address, "number");
 EGciSetINTEGER(tmp, 42);

http://www.ibm.com/rational
Contents Index Previous Next