MISR Toolkit  1.5.1
a_nodesa.c
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  Description: This file contains C routines that create and manipulate
4  aggregate nodes on an ODL tree.
5 
6  Author: Randy Davis, University of Colorado LASP
7 
8  Creation Date: 30 August 1990
9  Last Modified: 18 May 1991
10 
11  History:
12 
13  Creation - This set of routines was introduced in Version 2.0 of the
14  ODLC library, replacing the similar set of routines available in
15  Version 1 for manipulating object nodes.
16  a) The routines NewAggregate, RemoveAggregate, FindAggregate,
17  NextAggregate and ParentAggregate replace the routines NewObject,
18  RemoveObject, FindObject, NextObject and ParentObject that were
19  part of Version 1 of the ODLC library.
20  b) The function performed by the Version 1 routine NewODLTree
21  has been folded into routine NewAggregate.
22  c) New routines FindNextAggregate, CopyAggregate, CutAggregate and
23  PasteAggregate have been added to provide services useful for
24  label editors and similar programs.
25 
26  Version 2.1 - 13 March 1991 - Randy Davis, U. of Colorado LASP
27  a) Updated routines for cutting, copying and pasting aggregate nodes
28  and modified some of the existing routines to take advantage of
29  them.
30  b) Added handling for the comment and application-specific fields
31  that were added to aggregate nodes in Version 2.1.
32  c) Added routine NextSubAggregate to improve navigation capabilities.
33 
34  Version 2.2 - 18 May 1991 - M. DeMore, Jet Propulsion Laboratory
35  Removed include statements that were Unix specific and placed them
36  in odldef.h.
37 
38 *****************************************************************************/
39 
40 #include <stdlib.h>
41 #include "odldef.h"
42 #include "odlinter.h"
43 
44 
45 
46 
47 /*****************************************************************************
48 
49  Routine: NewAggregate
50 
51  Description: Inserts a new aggregate node into an ODL tree.
52 
53  Input:
54  base_node - A pointer to the node that will become the parent
55  of the new aggregate we are creating. If this pointer
56  is NULL, then the new node will be a root node for
57  a new ODL tree.
58  kind - Kind of node: object (KA_OBJECT) or group (KA_GROUP).
59  name - Pointer to a character string containing the new
60  node's name. A non-null name must be provided.
61  classType - If the new aggregate node is an object node, this
62  character string contains the object's class. It
63  may be NULL or a null string ("") if the class in
64  not specified. This argument is ignored for group
65  nodes.
66 
67  Output: A pointer to the new aggregate node is returned as the function
68  value. A value of NULL indicates that the new node could not be
69  created, probably due to a lack of dynamic memory. A NULL value
70  will also be returned if the name argument is NULL.
71 
72 *****************************************************************************/
73 
74 
76 
77  AGGREGATE base_node,
78  AGGREGATE_KIND kind,
79  char *name,
80  char *classType)
81 
82 {
83  AGGREGATE node; /* Pointer to the new aggregate node */
84  char *string; /* Pointer to created character string */
85 
86 
87  if (name == NULL)
88  {
89  return (NULL);
90  }
91 
92  /* Allocate memory for the new aggregate node */
93 
94  node = (AGGREGATE) malloc (AGGREGATE_NODE_SIZE);
95  if (node == NULL)
96  {
97  /* Error: couldn't get memory to hold this node */
98 
99  return (NULL);
100  }
101 
102  /* Set the node kind */
103 
104  node->kind = kind;
105 
106  /* Copy the node name */
107 
108  string = (char *) malloc (strlen (name)+1);
109  if (string == NULL)
110  {
111  /* Error: probably no memory available for name string. Free up
112  all space and return */
113 
114  free (node);
115  return (NULL);
116  }
117 
118  node->name = strcpy (string, name);
119 
120  /* Copy the class name. If this is a group node, or if it is an
121  object node but with no class name specified, then set the
122  class name to a null string */
123 
124  if (kind == KA_OBJECT && classType != NULL)
125  {
126  string = (char *) malloc (strlen (classType)+1);
127  if (string != NULL)
128  {
129  node->objClass = strcpy (string, classType);
130  }
131  }
132  else
133  {
134  string = (char *) malloc (1);
135  if (string != NULL)
136  {
137  node->objClass = strcpy (string, "");
138  }
139  }
140 
141  if (string == NULL)
142  {
143  /* Error: couldn't store class name, probably because of lack
144  of memory. Free up all space and return */
145 
146  free (node->name);
147  free (node);
148  return (NULL);
149  }
150 
151  /* Indicate no comment present as yet and initialize the
152  application-specific fields */
153 
154  node->comment = NULL;
155  node->appl1 = 0;
156  node->appl2 = 0;
157 
158  /* Indicate that there are no children of this node yet */
159 
160  node->first_child = NULL;
161  node->last_child = NULL;
162 
163  /* Indicate that there are no parameters for this node yet */
164 
165  node->first_parameter = NULL;
166  node->last_parameter = NULL;
167 
168  /* If there is a base node specified, attach the new node to it */
169 
170  if (base_node == NULL)
171  {
172  /* Make the new node a root node, with no parent or siblings */
173 
174  node->parent = NULL;
175  node->left_sibling = NULL;
176  node->right_sibling = NULL;
177  }
178  else
179  {
180  /* Attach the new aggregate node to the base node */
181 
182  PasteAggregate (base_node, node);
183  }
184 
185  return (node);
186 }
187 
188 
189 
190 
191 /*****************************************************************************
192 
193  Routine: RemoveAggregate
194 
195  Description: Removes an aggregate node and all its progeny.
196 
197  Input:
198  base_node - A pointer to the aggregate node to be removed.
199 
200  Output: A pointer to the next aggregate node belonging to the same parent
201  (the removed node's right sibling) is returned as function value.
202  The NULL value is returned if there is no right sibling. The NULL
203  value is also returned if the input argument is NULL.
204 
205 *****************************************************************************/
206 
207 
209 
210  AGGREGATE base_node)
211 
212 {
213  AGGREGATE node; /* Pointer to current node */
214  AGGREGATE r_node; /* Pointer to base nodes's right sibling */
215  PARAMETER parameter; /* Pointer to nodes's attributes and pointers */
216 
217 
218  if (base_node == NULL)
219  {
220  return (NULL);
221  }
222 
223  /* Remove all the progeny of the base node through recursive calls to
224  this function */
225 
226  node = base_node->first_child;
227 
228  while (node != NULL)
229  {
230  node = RemoveAggregate (node);
231  }
232 
233  /* Remove all the parameters and values attached to the base node */
234 
235  parameter = FirstParameter (base_node);
236 
237  while (parameter != NULL)
238  {
239  parameter = RemoveParameter (parameter);
240  }
241 
242  /* Save the location to the next aggregate in sequence, if any */
243 
244  r_node = base_node->right_sibling;
245 
246  /* Cut the base node from the tree */
247 
248  CutAggregate (base_node);
249 
250  /* Free up the memory space used to hold the node and the character
251  strings containing the node's name, class and comment */
252 
253  if(base_node->comment != NULL)
254  {
255  free (base_node->comment);
256  base_node->comment = NULL;
257  }
258  if(base_node->objClass != NULL)
259  {
260  free (base_node->objClass);
261  base_node->objClass = NULL;
262  }
263  if(base_node->name != NULL)
264  {
265  free (base_node->name);
266  base_node->name = NULL;
267  }
268  free (base_node);
269  base_node = NULL;
270 
271  /* Return a pointer to the next aggregate node in sequence, if any */
272 
273  return (r_node);
274 }
275 
276 
277 
278 
279 /*****************************************************************************
280 
281  Routine: ParentAggregate
282 
283  Description: Returns a pointer to an aggregate node's parent.
284 
285  Input:
286  base_node - A pointer to an aggregate node.
287 
288  Output: A pointer to the parent node. If the base node is the root node
289  of an ODL tree, then NULL is returned. The NULL value is also
290  returned if the input argument is NULL.
291 
292 *****************************************************************************/
293 
294 
296 
297  AGGREGATE base_node)
298 
299 {
300 
301  if (base_node == NULL)
302  {
303  return (NULL);
304  }
305  else
306  {
307  return (base_node->parent);
308  }
309 
310 }
311 
312 
313 
314 
315 /*****************************************************************************
316 
317  Routine: NextAggregate
318 
319  Description: Returns the aggregate node after the one pointed to by the
320  input parameter. The next node is determined using a preorder
321  traversal of the tree. Basically the scheme is as follows:
322  1) If the base node has children then its first child
323  is returned.
324  2) If a node has no children and is not the last child
325  of its parent, then the sibling to the immediate
326  right is returned.
327  3) Otherwise move to the node's parent and go back to
328  step 2.
329  4) If there is no next node then the value NULL will
330  be returned.
331 
332  Input:
333  base_node - A pointer to the starting aggregate node.
334 
335  Output: A pointer to the next node is returned as the function value.
336  A NULL value indicates that there is no next node. The NULL
337  value is also returned if the input argument is NULL.
338 
339 *****************************************************************************/
340 
341 
343 
344  AGGREGATE base_node)
345 
346 {
347  AGGREGATE node; /* Pointer to the next node */
348 
349 
350  if (base_node == NULL)
351  {
352  return (NULL);
353  }
354 
355  node = base_node;
356 
357  /* Check to see if the base node has children. If it does then
358  return the base nodes's first child */
359 
360  if (node->first_child != NULL)
361  {
362  node = node->first_child;
363  }
364  else
365  {
366  /* Search for a node in the ancestral path that has a
367  right sibling and return that sibling */
368 
369  while (node != NULL)
370  {
371  if (node->right_sibling != NULL)
372  {
373  node = node->right_sibling;
374  break;
375  }
376 
377  node = node->parent;
378  }
379  }
380 
381  return (node);
382 }
383 
384 
385 
386 
387 /*****************************************************************************
388 
389  Routine: NextSubAggregate
390 
391  Description: Returns the next aggregate node after the starting node that
392  is a sub-node of the base node. The nodes are visited in
393  pre-order. If there are no more sub-nodes of the base
394  node, the NULL value is returned.
395 
396  Input:
397  base_node - A pointer to the base aggregate node.
398  start_node - A pointer to the aggregate node for which the
399  next node is desired. The start node must
400  be the base node or a sub-node of the base node.
401 
402  Output: A pointer to the next node is returned as the function value.
403  A NULL value indicates that there is no next sub-node for the
404  base node. The NULL value is also returned if either of the
405  input arguments are NULL.
406 
407 *****************************************************************************/
408 
409 
411 
412  AGGREGATE base_node,
413  AGGREGATE start_node)
414 
415 {
416  AGGREGATE node; /* Pointer to the next node */
417 
418 
419  if (base_node == NULL || start_node == NULL)
420  {
421  return (NULL);
422  }
423 
424  node = start_node;
425 
426  /* Check to see if the start node has children. If it does then
427  return the start nodes's first child */
428 
429  if (node->first_child != NULL)
430  {
431  node = node->first_child;
432  }
433  else
434  {
435  /* Search for a sub-node of the base node that has a
436  right sibling and return that sibling */
437 
438  while (node != NULL)
439  {
440  if (node == base_node)
441  {
442  node = NULL;
443  break;
444  }
445  else if (node->right_sibling != NULL)
446  {
447  node = node->right_sibling;
448  break;
449  }
450 
451  node = node->parent;
452  }
453  }
454 
455  return (node);
456 }
457 
458 
459 
460 
461 /*****************************************************************************
462 
463  Routine: FindAggregate
464 
465  Description: Finds a node with a specified name. The search starts
466  with the base node and continues as necessary with all
467  of the base nodes's children, all their children, and
468  so on using a preorder search.
469 
470  Input:
471  base_node - A pointer to the starting aggregate node.
472  name - Pointer to a character string with the name of
473  the node to be located.
474 
475  Output: A pointer to the first node that has the specified name. If no
476  match is found, then the NULL value is returned. The NULL value
477  is also returned if either of the input arguments is NULL.
478 
479 *****************************************************************************/
480 
481 
483 
484  AGGREGATE base_node,
485  char *name)
486 
487 {
488  AGGREGATE node; /* Pointer to current node */
489 
490 
491  if (base_node == NULL || name == NULL)
492  {
493  return (NULL);
494  }
495 
496  /* Start searching with the base node and stop searching when we
497  find a node with the specified name or when we have visited
498  all of the sub-nodes of the base node */
499 
500  node = base_node;
501 
502  while (node != NULL && strcmp (node->name, name) != 0)
503  {
504  node = NextSubAggregate (base_node, node);
505  }
506 
507  return (node);
508 }
509 
510 
511 
512 
513 /*****************************************************************************
514 
515  Routine: FindNextAggregate
516 
517  Description: This routine is similar to routine FindAggregate in that it
518  searches the progeny of the specified base node, except that
519  the search begins with the node specified by the second
520  argument. This is useful when there is more than one node
521  with the same name in the search path.
522 
523  Input:
524  base_node - A pointer to the base node for the search.
525  start_node - A pointer to the starting node for the search. The
526  search does not include the start node.
527  name - Pointer to a character string with the name of the
528  node to be located.
529 
530  Output: A pointer to the next node that has the specified name. If no
531  match is found, then the NULL value is returned. The NULL
532  value is also returned if any of the input arguments are NULL.
533 
534 *****************************************************************************/
535 
536 
538 
539  AGGREGATE base_node,
540  AGGREGATE start_node,
541  char *name)
542 
543 {
544  AGGREGATE node; /* Pointer to current node */
545 
546 
547  if (base_node == NULL || start_node == NULL || name == NULL)
548  {
549  return (NULL);
550  }
551 
552  /* Start searching with the first node after the start node and stop
553  searching when we find a node with the specified name or when we
554  have visited all of the sub-nodes of the base node */
555 
556  node = NextSubAggregate (base_node, start_node);
557 
558  while (node != NULL && strcmp (node->name, name) != 0)
559  {
560  node = NextSubAggregate (base_node, node);
561  }
562 
563  return (node);
564 }
565 
566 
567 
568 
569 /*****************************************************************************
570 
571  Routine: CutAggregate
572 
573  Description: Detaches an aggregate node, along with its parameters and all
574  of it progeny, from an ODL tree.
575 
576  Input:
577  base_node - A pointer to the aggregate node to be cut.
578 
579  Output: A pointer to the cut node is returned as the function value. The
580  value will be NULL if the input argument is NULL.
581 
582 *****************************************************************************/
583 
584 
586 
587  AGGREGATE base_node)
588 
589 {
590  AGGREGATE parent; /* Pointer to base nodes's parent node */
591  AGGREGATE l_node; /* Pointer to base nodes's left sibling */
592  AGGREGATE r_node; /* Pointer to base nodes's right sibling */
593 
594 
595  if (base_node == NULL)
596  {
597  return (NULL);
598  }
599 
600  /* Remove the base node from the tree and patch pointers in other
601  nodes, as needed */
602 
603  parent = base_node->parent;
604  l_node = base_node->left_sibling;
605  r_node = base_node->right_sibling;
606 
607  if (l_node != NULL)
608  {
609  l_node->right_sibling = r_node;
610  }
611  else if (parent != NULL)
612  {
613  parent->first_child = r_node;
614  }
615 
616  if (r_node != NULL)
617  {
618  r_node->left_sibling = l_node;
619  }
620  else if (parent != NULL)
621  {
622  parent->last_child = l_node;
623  }
624 
625  /* Reset the parent and sibling pointers since this aggregate now
626  stands alone */
627 
628  base_node->parent = NULL;
629  base_node->left_sibling = NULL;
630  base_node->right_sibling = NULL;
631 
632  return (base_node);
633 }
634 
635 
636 
637 /*****************************************************************************
638 
639  Routine: CopyAggregate
640 
641  Description: Copy an aggregate node with all of its parameters and
642  all of the node's progeny (and their parameters).
643 
644  Input:
645  base_node - A pointer to the starting node to be copied. This
646  node remains in the ODL tree.
647 
648  Output: A pointer to the copy of the aggregate node is returned as the
649  function result. The result will be NULL if the input aggregate
650  node is NULL or if there is insufficient memory available to
651  complete the copy operation.
652 
653 *****************************************************************************/
654 
655 
657 
658  AGGREGATE base_node)
659 
660 {
661  AGGREGATE node_copy; /* Pointer to copy of base node */
662  AGGREGATE child_node; /* Pointer to current child aggregate node */
663  AGGREGATE child_copy; /* Pointer to copy of current child aggregate */
664  PARAMETER parameter; /* Pointer to current parameter of base node */
665  PARAMETER parameter_copy; /* Pointer to copy of current parameter */
666 
667 
668  if (base_node == NULL)
669  {
670  return (NULL);
671  }
672 
673  /* Create a new aggregate node for the copy */
674 
675  node_copy = NewAggregate (NULL, base_node->kind,
676  base_node->name, base_node->objClass);
677  if (node_copy == NULL)
678  {
679  /* Error: couldn't make a copy of the base node, probably
680  because we ran out of memory */
681 
682  return (NULL);
683  }
684 
685  /* Copy the comment attached to the node, if any */
686 
687  CommentAggregate (node_copy, base_node->comment);
688 
689  /* Copy all the aggregates's parameter nodes and their values and
690  attach them to the aggregate node */
691 
692  parameter = FirstParameter (base_node);
693 
694  while (parameter != NULL)
695  {
696  parameter_copy = CopyParameter (parameter);
697  PasteParameter (node_copy, parameter_copy);
698 
699  parameter = NextParameter (parameter);
700  }
701 
702  /* Call this routine recursively to copy all of the children
703  aggregate nodes */
704 
705  child_node = base_node->first_child;
706 
707  while (child_node != NULL)
708  {
709  /* Make a copy of the current child node */
710 
711  child_copy = CopyAggregate (child_node);
712  if (child_copy == NULL)
713  {
714  /* Error: we apparently ran out of memory while copying.
715  Rather than leave the copy operation only partially
716  complete, we release all space used and return */
717 
718  RemoveAggregate (node_copy);
719  return (NULL);
720  }
721 
722  /* Attach the copied child node to the copy of the base node */
723 
724  PasteAggregate (node_copy, child_copy);
725 
726  child_node = child_node->right_sibling;
727  }
728 
729  return (node_copy);
730 }
731 
732 
733 
734 /*****************************************************************************
735 
736  Routine: PasteAggregate
737 
738  Description: Attach an aggregate node (along with its parameters and
739  all of its progeny aggregate nodes) to the specified
740  aggregate node.
741 
742  Input:
743  base_node - A pointer to the node that will become the parent
744  to the inserted node.
745 
746  aggregate - A pointer to the aggregrate node to be attached.
747 
748  Output: A pointer to the attached aggregate node is returned as the
749  function value. If either of the input arguments is NULL,
750  the NULL value will be returned.
751 
752 *****************************************************************************/
753 
754 
756 
757  AGGREGATE base_node,
758  AGGREGATE aggregate)
759 
760 {
761  AGGREGATE old_last; /* Pointer to previously last child node */
762 
763 
764  if (base_node == NULL || aggregate == NULL)
765  {
766  return (NULL);
767  }
768 
769  /* Attach the new node to the base node, updating the pointers
770  in the previous and next aggregate nodes as necessary */
771 
772  old_last = base_node->last_child;
773  if (old_last != NULL)
774  {
775  old_last->right_sibling = aggregate;
776  }
777 
778  base_node->last_child = aggregate;
779  if (base_node->first_child == NULL)
780  {
781  base_node->first_child = aggregate;
782  }
783 
784  aggregate->parent = base_node;
785  aggregate->left_sibling = old_last;
786  aggregate->right_sibling = NULL;
787 
788  return (aggregate);
789 }
AGGREGATE ParentAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:295
PARAMETER CopyParameter()
AGGREGATE FindAggregate(AGGREGATE base_node, char *name)
Definition: a_nodesa.c:482
PARAMETER PasteParameter()
struct Parameter_Node * last_parameter
Definition: odldef.h:124
AGGREGATE RemoveAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:208
PARAMETER FirstParameter()
AGGREGATE PasteAggregate(AGGREGATE base_node, AGGREGATE aggregate)
Definition: a_nodesa.c:755
struct Aggregate_Node * last_child
Definition: odldef.h:122
AGGREGATE NextAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:342
struct Aggregate_Node * right_sibling
Definition: odldef.h:120
long appl2
Definition: odldef.h:117
char * comment
Definition: odldef.h:114
AGGREGATE_KIND kind
Definition: odldef.h:115
HDFFCLIBAPI intf intf _fcd string
struct Aggregate_Node * first_child
Definition: odldef.h:121
HDFFCLIBAPI _fcd name
AGGREGATE FindNextAggregate(AGGREGATE base_node, AGGREGATE start_node, char *name)
Definition: a_nodesa.c:537
long appl1
Definition: odldef.h:116
enum Aggregate_Kind AGGREGATE_KIND
Definition: odldef.h:88
struct Aggregate_Node * parent
Definition: odldef.h:118
struct Parameter_Node * first_parameter
Definition: odldef.h:123
AGGREGATE CutAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:585
struct Aggregate_Node * AGGREGATE
Definition: odldef.h:244
char * objClass
Definition: odldef.h:113
AGGREGATE CopyAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:656
int CommentAggregate(AGGREGATE aggregate, char *comment)
Definition: comments.c:51
PARAMETER NextParameter()
AGGREGATE NewAggregate(AGGREGATE base_node, AGGREGATE_KIND kind, char *name, char *classType)
Definition: a_nodesa.c:75
AGGREGATE NextSubAggregate(AGGREGATE base_node, AGGREGATE start_node)
Definition: a_nodesa.c:410
PARAMETER RemoveParameter()
char * name
Definition: odldef.h:112
struct Aggregate_Node * left_sibling
Definition: odldef.h:119
#define AGGREGATE_NODE_SIZE
Definition: odldef.h:264

MISR Toolkit - Copyright © 2005 - 2020 Jet Propulsion Laboratory
Generated on Fri Jun 19 2020 22:49:51