RexxCompoundTable.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /****************************************************************************/
39 /* REXX Kernel RexxCompoundTable.c */
40 /* */
41 /* Stem object table of compound variables */
42 /* */
43 /****************************************************************************/
44 #include "RexxCore.h"
45 #include "RexxCompoundTable.hpp"
46 #include "RexxCompoundElement.hpp"
47 #include "RexxCompoundTail.hpp"
48 
50  RexxStem *parentStem) /* the parent object we're embedded in */
51 {
52  setParent(parentStem); /* make the parent hook up */
53  setRoot(OREF_NULL); /* no root member */
54 }
55 
56 /**
57  * Copy all of the entries from another compound table into this
58  * table.
59  *
60  * @param other The source tail collection.
61  */
63  RexxCompoundTable &other)
64 {
65  RexxCompoundElement *entry = other.first();/* grab the first element */
66  while (entry != NULL)
67  { /* while we have more entry to process */
68  /* insert an entry in our table */
69  RexxCompoundElement *newEntry = findEntry(entry->getName(), true);
70  /* copy over the value */
71  newEntry->setValue(entry->variableValue);
72  entry = other.next(entry);
73  }
74 }
75 
77 {
78  setRoot(OREF_NULL); /* clear the anchor */
79 }
80 
81 
83 {
84  /* process the tail and search */
85  RexxCompoundTail resolved_tail(tail);
86  return findEntry(&resolved_tail, create);
87 }
88 
89 
91  RexxCompoundTail *tail, /* our tail search target */
92  bool create) /* we're creating a variable */
93 {
94  int rc = 0; /* comparison result */
95  RexxCompoundElement *previous; /* pointer for tree traversal */
96  RexxCompoundElement *anchor; /* pointer to current block */
97 
98  anchor = root; /* get root block */
99  previous = anchor; /* save starting point */
100  /* loop through on left branch*/
101  while (anchor)
102  {
103  /* do the name comparison */
104  rc = tail->compare(anchor->getName());
105  if (rc > 0)
106  { /* left longer? */
107  previous = anchor; /* save the previous */
108  /* take the right branch */
109  anchor = anchor->right;
110  continue; /* loop */
111  }
112  else if (rc < 0)
113  { /* left shorter? */
114  previous = anchor; /* save the previous */
115  /* the the left branch */
116  anchor = anchor->left;
117  continue; /* loop */
118  }
119  else
120  { /* names match */
121  return anchor; /* return the anchor */
122  }
123  }
124  if (!create)
125  { /* not a SET operation, */
126  return OREF_NULL; /* return var not found */
127  }
128  /* create a new compound variable */
129  ProtectedObject p_tailString(tail->makeString());
130  anchor = new_compoundElement(p_tailString);
131 
132  if (!previous)
133  { /* if first insertion */
134  anchor->setParent(OREF_NULL); /* no parent */
135  setRoot(anchor); /* set the tree top */
136  }
137  else
138  { /* real insertion */
139 
140  anchor->setParent(previous); /* set our parent entry */
141  if (rc > 0) /* should this be left or */
142  {
143  /* right on parent tree */
144  previous->setRight(anchor); /* right */
145  }
146  else
147  {
148  previous->setLeft(anchor); /* left */
149  }
150  balance(anchor); /* Balance the tree from here */
151  /* up */
152  }
153  return anchor; /* return new block pointer */
154 }
155 
156 
158  RexxCompoundElement *node) /* starting point */
159 {
160  RexxCompoundElement *_parent; /* block parent pointer */
161  unsigned short depth; /* current depth */
162  unsigned short wd; /* working depth */
163 
164  if (node == root) /* this the root? */
165  {
166  return; /* nothing to Balance */
167  }
168 
169  _parent = node->parent; /* step up to block's parent */
170  depth = 1; /* initial depth is 1 */
171 
172  while (_parent != OREF_NULL)
173  { /* while still have a parent */
174 
175  if (_parent->right == node)
176  { /* if on right branch */
177  _parent->rightdepth = depth; /* set right depth */
178  /* deeper on left? */
179  if (depth > (wd = _parent->leftdepth + (unsigned short)1))
180  {
181  moveNode(&_parent, false); /* adjust right branch */
182  depth = _parent->rightdepth; /* readjust depth */
183  }
184  else
185  {
186  if (wd < depth) /* left shorter */
187  {
188  return ; /* done */
189  }
190  }
191  }
192  else
193  {
194  _parent->leftdepth = depth; /* set left depth */
195  /* if right shorter */
196  if (depth > (wd = _parent->rightdepth + (unsigned short)1))
197  {
198  moveNode(&_parent, true); /* adjust left branch */
199  depth = _parent->leftdepth; /* readjust depth */
200  }
201  else
202  {
203  if (wd < depth) /* right shorter */
204  {
205  return ; /* done */
206  }
207  }
208  }
209  depth++; /* increment the depth */
210  node = _parent; /* step up to current */
211  _parent = _parent->parent; /* and lift up one more */
212  }
213 }
214 
216  RexxCompoundElement **anchor, /* node to move */
217  bool toright) /* move direction */
218 {
219  RexxCompoundElement *temp; /* anchor save position */
220  RexxCompoundElement *work; /* working block pointer */
221  RexxCompoundElement *work1; /* working block pointer */
222  RexxCompoundElement *work2; /* working block pointer */
223 
224  temp = *anchor; /* save where we are */
225 
226  if (toright)
227  { /* move right? */
228  work = temp->left; /* get left branch pointer */
229  work1 = temp->left = work->right; /* move right to left */
230  temp->leftdepth = work->rightdepth;/* adjust left depth value */
231  if (work1) /* was a right moved */
232  {
233  work1->setParent(temp); /* set its parent correctly */
234  }
235  work->setRight(temp); /* set new right */
236  work->rightdepth++; /* adjust its depth */
237  }
238  else
239  {
240  work = temp->right; /* get right node */
241  work1 = temp->right = work->left; /* move rights left node */
242  temp->rightdepth = work->leftdepth;/* set correct depth on left */
243  if (work1) /* moved a node */
244  {
245  work1->setParent(temp); /* set its parent correctly */
246  }
247  work->setLeft(temp); /* set left node */
248  work->leftdepth++; /* adjust its depth */
249  }
250  work->setParent(temp->parent); /* move node's parent around */
251  work2 = temp->parent;
252  temp->setParent(work); /* so that top is correct */
253  if (work2 == OREF_NULL) /* is this new root? */
254  {
255  setRoot(work); /* yes, adjust the root */
256  }
257  else if (work2->left == temp) /* was it on left */
258  {
259  work2->setLeft(work); /* make it left */
260  }
261  else
262  {
263  work2->setRight(work); /* else make it right */
264  }
265  *anchor = work; /* return correct position */
266 }
267 
268 
270 {
271  if (root == OREF_NULL)
272  {
273  return OREF_NULL;
274  }
275  else
276  {
277  return findLeaf(root);
278  }
279 }
280 
281 
283  RexxCompoundElement *node) /* starting point we're drilling from */
284 {
285  for (;;)
286  {
287  while (node->left != OREF_NULL)
288  { /* go as far left as we can */
289  node = node->left;
290  }
291  if (node->right == OREF_NULL)
292  { /* if there is no right child, stop here */
293  return node;
294  }
295  node = node->right; /* go right one level and repeat */
296  }
297 }
298 
299 
301  RexxCompoundElement *node) /* starting point we're drilling from */
302 {
303  /* get the parent node */
304  RexxCompoundElement *_parent = node->parent;
305  if (_parent != OREF_NULL)
306  {
307  if (_parent->right == node)
308  { /* if coming back up from the right */
309  return _parent; /* this node's turn has come */
310  }
311  if (_parent->right != OREF_NULL)
312  { /* if no right child, do this one immediately */
313  return findLeaf(_parent->right);/* drill down the other branch */
314  }
315  return _parent;
316  }
317  return OREF_NULL; /* we've reached the top */
318 }
319 
320 
322  RexxStem *parentStem)
323 /******************************************************************************/
324 /* Function: Set the parent for a compound table. N.B., this cannot be an */
325 /* inline method because of circular header file dependencies between */
326 /* RexxCompoundTable and RexxStem. */
327 /******************************************************************************/
328 {
329  // NOTE: This seems a little weird, but we're doing the set using the parent
330  // object...which will actually set the value in our own object instance.
331  // This is done because the if we have checkSetOref turned on, the validity
332  // checker won't recognize our address as being a valid object because it's
333  // embedded within another Rexx object.
334  OrefSet(parentStem, parentStem->tails.parent, parentStem);
335 }
336 
337 
339  RexxCompoundElement *newRoot)
340 /******************************************************************************/
341 /* Function: Set the root node for a compound table. N.B., this cannot be an*/
342 /* inline method because of circular header file dependencies between */
343 /* RexxCompoundTable and RexxStem. */
344 /******************************************************************************/
345 {
346  // NOTE: This seems a little weird, but we're doing the set using the parent
347  // object...which will actually set the value in our own object instance.
348  // This is done because the if we have checkSetOref turned on, the validity
349  // checker won't recognize our address as being a valid object because it's
350  // embedded within another Rexx object.
351  OrefSet(parent, parent->tails.root, newRoot);
352 }
353 
354 
356 /******************************************************************************/
357 /* Function: Search for a compound entry. This version is optimized for */
358 /* "find-but-don't create" usage. */
359 /******************************************************************************/
360 {
361  int rc; /* comparison result */
362  RexxCompoundElement *anchor; /* pointer to current block */
363 
364  anchor = root; /* get root block */
365  /* loop through on left branch*/
366  while (anchor != NULL)
367  {
368  /* do the name comparison */
369  rc = tail->compare(anchor->getName());
370  if (rc > 0)
371  { /* left longer? */
372  /* take the right branch */
373  anchor = anchor->right;
374  continue; /* loop */
375  }
376  else if (rc < 0)
377  { /* left shorter? */
378  /* the the left branch */
379  anchor = anchor->left;
380  continue; /* loop */
381  }
382  else
383  { /* names match */
384  return anchor; /* return the anchor */
385  }
386  }
387  return OREF_NULL; /* return var not found */
388 }
RexxCompoundElement * new_compoundElement(RexxString *s)
#define OREF_NULL
Definition: RexxCore.h:61
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
void setLeft(RexxCompoundElement *leftChild)
void setRight(RexxCompoundElement *rightChild)
RexxCompoundElement * left
void setValue(RexxObject *value)
RexxCompoundElement * right
void setParent(RexxCompoundElement *parentElement)
RexxCompoundElement * parent
void copyFrom(RexxCompoundTable &other)
void setRoot(RexxCompoundElement *newRoot)
RexxCompoundElement * findEntry(RexxCompoundTail *tail)
void init(RexxStem *parent)
RexxCompoundElement * root
void moveNode(RexxCompoundElement **anchor, bool toright)
RexxCompoundElement * first()
RexxCompoundElement * next(RexxCompoundElement *node)
RexxCompoundElement * findLeaf(RexxCompoundElement *node)
void balance(RexxCompoundElement *node)
void setParent(RexxStem *parent)
RexxString * makeString()
int compare(RexxString *name)
RexxCompoundTable tails
Definition: StemClass.hpp:159
RexxObject * variableValue
RexxString * getName()
char work[256]