RexxCollection.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 RexxCollection.cpp */
40 /* */
41 /* Primitive HashTableCollection Class */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "RexxCollection.hpp"
47 #include "StringClass.hpp"
48 #include "ArrayClass.hpp"
49 #include "DirectoryClass.hpp"
50 #include "Interpreter.hpp"
51 
52 void RexxHashTableCollection::live(size_t liveMark)
53 /******************************************************************************/
54 /* Function: Normal garbage collection live marking */
55 /******************************************************************************/
56 {
57  memory_mark(this->contents);
58  memory_mark(this->objectVariables);
59 }
60 
62 /******************************************************************************/
63 /* Function: Generalized object marking */
64 /******************************************************************************/
65 {
67  memory_mark_general(this->objectVariables);
68 }
69 
71 /******************************************************************************/
72 /* Function: Flatten an object */
73 /******************************************************************************/
74 {
76 
77  flatten_reference(newThis->contents, envelope);
78  flatten_reference(newThis->objectVariables, envelope);
79 
81 }
82 
84 /******************************************************************************/
85 /* Function: unflatten an object */
86 /******************************************************************************/
87 {
88  envelope->addTable(this);
89  return this;
90 }
91 
93 /******************************************************************************/
94 /* Function: Create a proxy object for a standard collection */
95 /******************************************************************************/
96 {
97  /* Determine which special object */
98  /* this is and compute code for it. */
99  if (this == TheEnvironment) /* the environment directory */
100  {
101  return new_proxy(CHAR_ENVIRONMENT);
102  }
103  else if (this == TheKernel) /* the kernel directory */
104  {
105  return new_proxy(CHAR_KERNEL);
106  }
107  else if (this == TheSystem) /* the system directory */
108  {
109  return new_proxy(CHAR_SYSTEM);
110  }
111  else
112  {
113  Interpreter::logicError("Don't know how to generate a proxy object for an object");
114  }
115  return OREF_NULL;
116 }
117 
118 
120 /******************************************************************************/
121 /* Function: Copy a hash based collection object */
122 /******************************************************************************/
123 {
124  /* make a copy of ourself (this also */
125  /* copies the object variables */
127  /* We copy the Hash table as well */
128  OrefSet(newObj, newObj->contents, (RexxHashTable *)this->contents->copy());
129  return newObj; /* return the new object */
130 }
131 
133 /******************************************************************************/
134 /* Function: Return all of the collection indices in an array */
135 /******************************************************************************/
136 {
137  return this->contents->makeArray();
138 }
139 
141 /******************************************************************************/
142 /* Arguments: Value, index */
143 /* */
144 /* Returned: Nothing */
145 /******************************************************************************/
146 {
147  // put this in with duplicate protection
148  RexxHashTable *newHash = this->contents->putNodupe(_value, _index);
149  // the put can expand, so protect against that
150  if (newHash != OREF_NULL)
151  {
152  OrefSet(this, this->contents, newHash);
153  }
154  return OREF_NULL;
155 }
156 
157 
158 /**
159  * The exported remove() method for hash collection
160  * classes. This is the Rexx stub method. The removal
161  * operation is delegated to the virtual method defined
162  * by the implementing class.
163  *
164  * @param _index The target removal index.
165  *
166  * @return The removed object, or .nil if the index was not found.
167  */
169 {
170  requiredArgument(_index, OREF_positional, ARG_ONE); /* make sure we have an index */
171 
172  RexxObject *removedItem = this->remove(_index); /* remove the item */
173  if (removedItem == OREF_NULL) /* If nothing found, give back .nil */
174  {
175  /* (never return OREF_NULL to REXX) */
176  return TheNilObject;
177  }
178  return removedItem; /* return removed value */
179 }
180 
181 
182 /**
183  * Base virtual function for a table remove operation.
184  * This applies object equality semantics to the operation.
185  *
186  * @param _index The object index.
187  *
188  * @return The removed object.
189  */
191 {
192  return this->contents->remove(_index);
193 }
194 
195 
197  RexxObject *_index) /* target index */
198 /******************************************************************************/
199 /* Arguments: Index */
200 /* */
201 /* Returned: Array of all values with the same index */
202 /******************************************************************************/
203 {
204  requiredArgument(_index, OREF_positional, ARG_ONE); /* make sure we have an index */
205  /* do the get */
206  return this->contents->getAll(_index);
207 }
208 
209 /**
210  * Exported get() accessor for a hash table collection.
211  * This delegates to a virtual method defined by the
212  * target collection.
213  *
214  * @param _index The target index.
215  *
216  * @return The fetched object, or .nil if the index does not
217  * exist in the collection.
218  */
220 {
221  requiredArgument(_index, OREF_positional, ARG_ONE); /* make sure we have an index */
222  RexxObject *object = this->get(_index); /* get the item */
223  if (object == OREF_NULL) /* If nothing found, give back .nil */
224  {
225  return TheNilObject; /* (never return OREF_NULL to REXX) */
226  }
227  return object; /* return the item */
228 }
229 
230 
231 /**
232  * Retrieve an item from a hash collection using a key.
233  * This is the base virtual implementation, which uses
234  * equality semantics for the retrieveal. Other implementations
235  * may override this.
236  *
237  * @param key The target key.
238  *
239  * @return The retrieved object. Returns OREF_NULL if the object
240  * was not found.
241  */
243 {
244  return this->contents->get(key);
245 }
246 
247 
248 /**
249  * Exported Rexx method for adding an item to a collection.
250  * The put operation is delegated to the implementing
251  * class virtual function.
252  *
253  * @param _value The value to add.
254  * @param _index The index for the added item.
255  *
256  * @return Always returns OREF_NULL.
257  */
259 {
260  requiredArgument(_value, OREF_positional, ARG_ONE); /* make sure we have an value */
261  requiredArgument(_index, OREF_positional, ARG_TWO); /* make sure we have an index */
262  /* try to place in existing hashtab */
263  return this->put(_value, _index);
264 }
265 
266 
267 /**
268  * Place an item into a hash collection using a key.
269  * This is the base virtual implementation, which uses
270  * equality semantics for the retrieveal. Other implementations
271  * may override this.
272  *
273  * @param _value The inserted value.
274  * @param _index The insertion key.
275  *
276  * @return The retrieved object. Returns OREF_NULL if the object
277  * was not found.
278  */
280 {
281  /* try to place in existing hashtab */
282  RexxHashTable *newHash = this->contents->put(_value, _index);
283  if (newHash != OREF_NULL) /* have a reallocation occur? */
284  {
285  /* hook on the new hash table */
286  OrefSet(this, this->contents, newHash);
287  }
288  return OREF_NULL; /* always return nothing */
289 }
290 
292  RexxObject *_value, /* object to add */
293  RexxObject *_index) /* added index */
294 /******************************************************************************/
295 /* Arguments: Value, index */
296 /* */
297 /* Returned: Nothing */
298 /******************************************************************************/
299 {
300  requiredArgument(_value, OREF_positional, ARG_ONE); /* make sure we have an value */
301  requiredArgument(_index, OREF_positional, ARG_TWO); /* make sure we have an index */
302  return add(_value, _index);
303 }
304 
306  RexxObject *_value, /* object to add */
307  RexxObject *_index) /* added index */
308 /******************************************************************************/
309 /* Arguments: Value, index */
310 /* */
311 /* Returned: Nothing */
312 /******************************************************************************/
313 {
314  /* try to place in existing hashtab */
315  RexxHashTable *newHash = this->contents->add(_value, _index);
316  if (newHash != OREF_NULL) /* have a reallocation occur? */
317  {
318  /* hook on the new hash table */
319  OrefSet(this, this->contents, newHash);
320  }
321  return OREF_NULL; /* always return nothing */
322 }
323 
325  RexxHashTableCollection * target) /* merge "partner" collection */
326 /******************************************************************************/
327 /* Function: Merge a hash table collection into another similar collection. */
328 /******************************************************************************/
329 {
330  return this->contents->merge(target);
331 }
332 
333 
335  int depth) /* depth to propagate the copy to */
336 /******************************************************************************/
337 /* Arguments: Recursion depth */
338 /* */
339 /* Returned: Nothing */
340 /******************************************************************************/
341 {
342  /* Get hash table. */
343  RexxHashTable *hashTable = this->contents;
344  /* For all indices. */
345  for (HashLink i = hashTable->first(); i < hashTable->totalSlotsSize(); i = hashTable->next(i))
346  {
347  RexxObject *_value = hashTable->value(i); /* Get this value */
348  RexxObject *valueCopy = _value->copy(); /* make a copy. */
349  hashTable->replace(valueCopy, i); /* Replace original w/ copy */
350  if (depth > 1) /* gone depth requested. */
351  /* nope, copy these values */
352  ((RexxHashTableCollection *)valueCopy)->copyValues(depth-1);
353  }
354 
355  return OREF_NULL;
356 }
357 
358 
359 /**
360  * Test for the existence of an index in the collection.
361  * This uses the get() virtual function to determine if
362  * the item exists.
363  *
364  * @param _index The target index.
365  *
366  * @return True if the index exists, false if the index does not
367  * exist.
368  */
370 {
371  requiredArgument(_index, OREF_positional, ARG_ONE); /* make sure we have an index */
372  /* try to get the item */
373  RexxObject *_value = this->get(_index);
374  /* tell caller if we succeeded */
375  return(_value != OREF_NULL) ? (RexxObject *)TheTrueObject : (RexxObject *)TheFalseObject;
376 }
377 
378 
379 /**
380  * Retrieve an index for a given item. Which index is returned
381  * is indeterminate.
382  *
383  * @param target The target object.
384  *
385  * @return The index for the target object, or .nil if no object was
386  * found.
387  */
389 {
390  // required argument
391  requiredArgument(target, OREF_positional, ARG_ONE);
392  // retrieve this from the hash table
393  RexxObject *result = this->getIndex(target);
394  // not found, return .nil
395  if (result == OREF_NULL)
396  {
397  return TheNilObject;
398  }
399  return result;
400 }
401 
402 
403 /**
404  * Retrieve an index for a given item. Which index is returned
405  * is indeterminate.
406  *
407  * @param target The target object.
408  *
409  * @return The index for the target object, or .nil if no object was
410  * found.
411  */
413 {
414  // retrieve this from the hash table
415  return contents->getIndex(target);
416 }
417 
418 
419 /**
420  * Exported method to remove an item specified by value.
421  *
422  * @param target The target object.
423  *
424  * @return The target object again.
425  */
427 {
428  // required argument
429  requiredArgument(target, OREF_positional, ARG_ONE);
430  // the actual target class may use different semantics for this.
431  return this->removeItem(target);
432 }
433 
434 
435 /**
436  * Remove an item specified by value.
437  *
438  * @param target The target object.
439  *
440  * @return The target object again.
441  */
443 {
444  // the contents handle all of this.
445  return this->contents->removeItem(target);
446 }
447 
448 
449 /**
450  * Test if a given item exists in the collection.
451  *
452  * @param target The target object.
453  *
454  * @return .true if the object exists, .false otherwise.
455  */
457 {
458  requiredArgument(target, OREF_positional, ARG_ONE);
459  return this->hasItem(target);
460 }
461 
462 
463 /**
464  * Test if a given item exists in the collection.
465  *
466  * @param target The target object.
467  *
468  * @return .true if the object exists, .false otherwise.
469  */
471 {
472  return this->contents->hasItem(target);
473 }
474 
475 
477 /******************************************************************************/
478 /* Function: create a table supplier */
479 /******************************************************************************/
480 {
481  /* get the hashtab supplier */
482  return this->contents->supplier();
483 }
484 
486 /******************************************************************************/
487 /* Function: retrieve all items of the collection. */
488 /******************************************************************************/
489 {
490  return this->contents->allItems();
491 }
492 
494 /******************************************************************************/
495 /* Function: retrieve all indexes of the collection. */
496 /******************************************************************************/
497 {
498  return this->contents->allIndexes();
499 }
500 
501 /**
502  * Return the unique indexes in a hash collection.
503  *
504  * @return The set of uniqueIndexes
505  */
507 {
508  return this->contents->uniqueIndexes();
509 }
510 
511 
512 /**
513  * Empty a hash table collection.
514  *
515  * @return nothing
516  */
518 {
519  contents->empty();
520  return OREF_NULL;
521 }
522 
523 
524 /**
525  * Test if a HashTableCollection is empty.
526  *
527  * @return
528  */
530 {
532 }
#define OREF_NULL
Definition: RexxCore.h:61
#define TheSystem
Definition: RexxCore.h:188
#define TheKernel
Definition: RexxCore.h:187
#define TheEnvironment
Definition: RexxCore.h:183
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
const int ARG_TWO
Definition: RexxCore.h:84
#define TheNilObject
Definition: RexxCore.h:191
#define TheFalseObject
Definition: RexxCore.h:195
const int ARG_ONE
Definition: RexxCore.h:83
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
size_t HashLink
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
RexxString * new_proxy(const char *name)
static void logicError(const char *desc, const char *info1=NULL, size_t info2=0)
void addTable(RexxObject *obj)
RexxObject * copyValues(int depth)
virtual RexxObject * get(RexxObject *key)
RexxObject * removeRexx(RexxObject *)
void liveGeneral(int reason)
virtual RexxObject * removeItem(RexxObject *value)
virtual RexxObject * remove(RexxObject *key)
RexxObject * getRexx(RexxObject *)
virtual RexxObject * mergeItem(RexxObject *, RexxObject *)
void flatten(RexxEnvelope *)
virtual RexxObject * hasItem(RexxObject *)
RexxObject * hasItemRexx(RexxObject *)
RexxObject * merge(RexxHashTableCollection *)
RexxHashTable * contents
RexxObject * makeProxy(RexxEnvelope *)
virtual RexxObject * add(RexxObject *, RexxObject *)
RexxObject * allAt(RexxObject *)
RexxObject * indexRexx(RexxObject *value)
RexxSupplier * supplier()
virtual RexxObject * getIndex(RexxObject *value)
RexxObject * hasIndexRexx(RexxObject *)
RexxObject * putRexx(RexxObject *, RexxObject *)
RexxObject * unflatten(RexxEnvelope *)
RexxObject * addRexx(RexxObject *, RexxObject *)
virtual RexxObject * put(RexxObject *, RexxObject *)
RexxObject * removeItemRexx(RexxObject *value)
RexxSupplier * supplier()
RexxHashTable * add(RexxObject *value, RexxObject *key)
RexxObject * getIndex(RexxObject *value)
RexxObject * merge(RexxHashTableCollection *target)
RexxArray * getAll(RexxObject *key)
RexxArray * makeArray()
RexxHashTable * putNodupe(RexxObject *value, RexxObject *key)
RexxArray * allItems()
HashLink first()
RexxHashTable * put(RexxObject *value, RexxObject *key)
RexxArray * uniqueIndexes()
RexxObject * hasItem(RexxObject *value, RexxObject *key)
RexxObject * remove(RexxObject *key)
RexxObject * removeItem(RexxObject *value, RexxObject *key)
RexxArray * allIndexes()
RexxObject * get(RexxObject *key)
RexxObject * value(HashLink position)
HashLink next(HashLink position)
RexxObject * replace(RexxObject *value, HashLink position)
virtual RexxObject * copy()
RexxObject * copy()