Obtaining IDL Structure Tags Recursively
QUESTION: Does anyone have a "recursive" Tag_Names like function? I would like to pass in a structure and get back a string array with members down to the bottom level. For example:
IDL> input = {a:{m,n}, b:{r,s,t}, c, d, e}
IDL> output = Recursive_Tag_Names_Function(input)
IDL> Print, output
'input.a.m', 'input.a.n', 'input.b.r', 'input.b.s', 'input.b.t',
'input.c', 'input.d', 'input.e'
![]()
ANSWER: It must have been a slow news day, or something, but for some reason this question intrigued me. I thought something like this might be useful for the object programming I am doing.
So here it is. There is a little main-level program below the two program modules that exercises the principle program, Get_Tags. If you just pass the structure to the program, you get all the fields with a "dot" in front of the names. For example,
IDL> tags = Get_Tags(struct)
returns:
.one .one.two .one.two.three
etc. If you want the full name back, pass a second positional parameter that is the root name of the structure. For example,
IDL> tags = Get_Tags(struct, 'struct')
returns:
struct.one struct.one.two struct.one.two.three
Note that the string vector that is actually returned from the Get_Tags function is in all UPPERCASE characters.
![]()
Function All_Tags, structure, rootname
; This is a function that recursively searches through
; a structure tree, finding ALL of the structure's field names.
; It returns a pointer to an array of pointers, each pointing
; to the names of structure fields.
IF N_Elements(rootname) EQ 0 THEN rootname = '.' ELSE $
rootname = StrUpCase(rootname) + '.'
names = Tag_Names(structure)
retValue = Ptr_New(rootname + names)
; If any of the fields are structures, report them too.
FOR j=0,N_Elements(names)-1 DO BEGIN
ok = Execute('s = Size(structure.' + names[j] + ')')
IF s[s[0]+1] EQ 8 THEN BEGIN
newrootname = rootname + names[j]
theseNames = Call_Function('All_Tags', $
structure.(j), newrootname)
retValue = [[retValue],[theseNames]]
ENDIF
ENDFOR
RETURN, retValue
END
;-------------------------------------------------------------------
FUNCTION Get_Tags, structure, rootname
; This function returns the names of all structure fields
; in the structure as a string array. The names are given
; as valid structure names from the root structure name,
; which can be passed in along with the structure itself.
On_Error, 1
; Check parameters.
CASE N_Params() OF
0: BEGIN
Message, 'Structure argument is required.'
ENDCASE
1: BEGIN
rootname = ''
s = Size(structure)
IF s[s[0]+1] NE 8 THEN $
Message, 'Structure argument is required.'
ENDCASE
2: BEGIN
s = Size(structure)
IF s[s[0]+1] NE 8 THEN $
Message, 'Structure argument is required.'
s = Size(rootname)
IF s[s[0]+1] NE 7 THEN $
Message, 'Root Name parameter must be a STRING'
ENDCASE
ENDCASE
tags = All_Tags(structure, rootname)
; Extract and free the first pointer.
retval = [*tags[0,0]]
Ptr_Free, tags[0,0]
; Extract and free the the rest of the pointers.
s = Size(tags)
FOR j=1,s[2]-1 DO BEGIN
retval = [retval, *tags[0,j]]
Ptr_Free, tags[0,j]
ENDFOR
Ptr_Free, tags
; Return the structure names.
RETURN, retval
END
; Main-level program to exercise Get_Tags.
d = {dog:'spot', cat:'fuzzy'}
c = {spots:4, animals:d}
b = {fast:c, slow:-1}
a = {cars:b, pipeds:c, others:'man'}
tags = Get_Tags(a)
s = Size(tags)
For j=0,s[1]-1 Do Print, tags[j]
END
![]()
Copyright © 1998 David W. Fanning
Last Updated 3 June 1998
