String Processing
A number of functions exist to simplify the processing of IDL_STRING descriptors. By using these functions instead of doing your own string management, you can eliminate a common source of errors.
Topics included in this section include:
- Accessing IDL_STRING Values
- Copying Strings - IDL_StrDup()
- Deleting Strings - IDL_StrDelete()
- Setting an IDL_STRING Value - IDL_StrStore()
- Obtaining a String of Given Length - IDL_StrEnsureLength()
Accessing IDL_STRING Values
It is important to realize that the s field of an IDL_STRING struct does not contain a valid string pointer in the case of a null string (i.e., when slen is zero). A common error that can cause IDL to crash is illustrated by the following code fragment:
void print_str(IDL_STRING *s)
{
printf("%s", s->s);
}
The problem with this code is that it fails to consider the case where the argument s describes a NULL string. The proper way to write this code is as follows:
void print str(IDL_STRING *s)
{
printf("%s", IDL_STRING_STR(s));
}
The macro IDL_STRING_STR takes as its argument a pointer to an IDL_STRING struct. If the string is null, it returns a pointer to a zero length null-terminated string, otherwise it returns the string pointer from the struct. Consistent use of this macro will avoid the most common sort of error involving strings.
It is common for IDL system routines to accept arguments that provide names. Such arguments must be scalar strings, or string arrays that contain a single element. To properly process such an argument, it is necessary to screen out non-string types or multi-element arrays, locate the string descriptor, and use the IDL_STRING_STR() macro to extract a usable NULL terminated C string from it. The IDL_VarGetString() is used for this purpose. It encapsulates all of the error checking, and always returns a pointer to a NULL terminated C string, throwing the proper IDL_MSG_LONGJMP error via the IDL_Message() function when this is not possible:
char *IDL_VarGetString(IDL_VPTR v)
where
v
Variable from which string value is desired.
Copying Strings - IDL_StrDup()
It is often necessary to copy one string to another. Assume, for example, that there are two string descriptors s_src and s_dst, and that s_dst contains garbage. It would almost suffice to copy the contents of s_src into s_dst. The reason this is not quite correct is that both descriptors would then contain a pointer to the same string. This aliasing can cause some strange effects, or even cause IDL to crash if one of the two descriptors is freed and the string from the other is accessed.
IDL_StrDup() takes care of this problem by allocating memory for a second copy of the string, and replacing the string pointer in the descriptor with a pointer to the fresh copy. Naturally, if the string descriptor is for a NULL string, nothing is done.
void IDL_StrDup(IDL_STRING *str, IDL_MEMINT n)
where:
str
Pointer to one or more IDL_STRING descriptors which need their strings duplicated.
n
The number of descriptors. The proper way to copy a string is:
s_dst = s_src; /* Copy the descriptor */
IDL_StrDup(&s_dst, 1L); /* Duplicate the string */
Deleting Strings - IDL_StrDelete()
Before an IDL_STRING can be discarded or re-used, it is important to release any dynamic memory it might be using. The IDL_StrDelete() function should be used to delete strings:
void IDL_StrDelete(IDL_STRING *str, IDL_MEMINT n)
where:
str
Pointer to one or more IDL_STRING descriptors which need their contents freed.
n
The number of descriptors.
IDL_StrDelete() deletes all dynamic memory used by the IDL_STRINGs. The descriptors contain garbage once this has been done, and their contents should not be used.
The IDL_Deltmp() function automatically calls IDL_StrDelete() when returning temporary variables of type IDL_TYP_STRING, so it is not necessary or desirable to call IDL_StrDelete() explicitly in this case.
Setting an IDL_STRING Value - IDL_StrStore()
The IDL_StrStore() function should be used to store a null-terminated C string into an IDL_STRING descriptor:
void IDL_StrStore(IDL_STRING *s, char *fs)
where:
s
Pointer to an IDL_STRING descriptor. This descriptor is assumed to contain garbage, so call IDL_StrDelete() on it first if this is not the case.
fs
Pointer to the null-terminated string to be copied into s.
IDL_StrStore() is useful for placing a string value into an IDL_STRING. This IDL_STRING does not need to be a component of a VARIABLE, which makes this function very flexible.
One often needs a temporary, scalar VARIABLE of type IDL_TYP_STRING with a given value. The function IDL_StrToSTRING() fills this need:
IDL_VPTR IDL_StrToSTRING(char *s)
where:
s
Pointer to the null-terminated string to be copied into the resulting temporary variable.
Obtaining a String of a Given Length - IDL_StrEnsureLength()
Sometimes you need to make sure that the string in an IDL_STRING descriptor has a specific length. The IDL_StrEnsureLength() function can be used in this case:
void IDL_StrEnsureLength(IDL_STRING *s, int n)
where:
s
A pointer to the IDL_STRING that will have its length checked.
n
The number of characters the string must be able to contain, not including the terminating NULL character.
If the IDL_STRING passed already has enough room for the specified number of characters, it is not re-allocated. Otherwise, the existing string is freed and a new string of sufficient length is allocated. In either case, the slen field of the IDL_STRING will be set to the requested length.
If a new dynamic string is allocated, it will contain garbage values because IDL_StrEnsureLength() only allocates memory of the specified size, it does not copy a value into it. Therefore, the calling routine must copy a null-terminated string into the new dynamic string.