DirectoryClass.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 */
40 /* */
41 /* Primitive Directory Class */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "DirectoryClass.hpp"
48 #include "ArrayClass.hpp"
49 #include "MethodClass.hpp"
50 #include "RexxActivation.hpp"
51 #include "ProtectedObject.hpp"
52 
53 // singleton class instance
55 
56 
57 /**
58  * Create initial class object at bootstrap time.
59  */
61 {
62  CLASS_CREATE(Directory, "Directory", RexxClass);
63 }
64 
65 void RexxDirectory::live(size_t liveMark)
66 /******************************************************************************/
67 /* Function: Normal garbage collection live marking */
68 /******************************************************************************/
69 {
70  this->RexxHashTableCollection::live(liveMark);
73 }
74 
76 /******************************************************************************/
77 /* Function: Generalized object marking */
78 /******************************************************************************/
79 {
83 }
84 
86 /******************************************************************************/
87 /* Function: Flatten an object */
88 /******************************************************************************/
89 {
91 
92  flatten_reference(newThis->contents, envelope);
93  flatten_reference(newThis->method_table, envelope);
94  flatten_reference(newThis->unknown_method, envelope);
95  flatten_reference(newThis->objectVariables, envelope);
96 
98 }
99 
101 /******************************************************************************/
102 /* Function: unflatten an object */
103 /******************************************************************************/
104 {
105  envelope->addTable(this); /* add to the envelope table */
106  return this; /* and just return out selves */
107 }
108 
110 /******************************************************************************/
111 /* Function: Copy a directory */
112 /******************************************************************************/
113 {
114  /* copy object via Collection copy */
116  /* No specifics for Directory. */
117  if (this->method_table != OREF_NULL)
118  {
119  ProtectedObject p(newObj);
120  /* copy it too */
121  OrefSet(newObj, newObj->method_table, (RexxTable *)this->method_table->copy());
122  }
123  return newObj; /* return the copy */
124 }
125 
127  RexxString *entryName) /* name to retrieve */
128 /******************************************************************************/
129 /* Function: Retrieve an entry from a directory...with upper casing */
130 /* */
131 /* Returned: The entry, or the result of running the method */
132 /******************************************************************************/
133 {
134  entryName = entryName->upper(); /* force to uppercase */
135  return this->at(entryName); /* just return the "at" form */
136 }
137 
139 /******************************************************************************/
140 /* Function: Return the count of items in the directory, including the */
141 /* number of methods added via set method calls */
142 /******************************************************************************/
143 {
144  /* get the direct table size */
145  size_t count = this->contents->totalEntries();
146  /* have a method table? */
147  if (this->method_table != OREF_NULL)
148  {
149  /* add in the count of methods */
150  count += this->method_table->items();
151  }
152  return count; /* return this amount */
153 }
154 
156 /******************************************************************************/
157 /* Function: Return the count of items in the directory, including the */
158 /* number of methods added via set method calls */
159 /******************************************************************************/
160 {
161  return (RexxObject *)new_integer(this->items());
162 }
163 
165 /******************************************************************************/
166 /* Function: Create a supplier for a directory, including the results of all */
167 /* of the SETMETHOD methods as values */
168 /******************************************************************************/
169 {
170  RexxTable *result = new_table(); /* get a table for the supplier */
171  ProtectedObject p(result);
172  RexxHashTable *hashTab = this->contents; /* point to the contents */
173  /* now traverse the entire table */
174  for (HashLink i = hashTab->first(); hashTab->index(i) != OREF_NULL; i = hashTab->next(i))
175  {
176  /* get the directory index */
177  RexxString *name = (RexxString *)hashTab->index(i);
178  /* add to the table */
179  result->put(hashTab->value(i), name);
180  }
181  /* have a method table? */
182  if (this->method_table != OREF_NULL)
183  {
184  RexxTable *methodTable = this->method_table;
185  /* need to extract method values */
186  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i))
187  {
188  /* get the directory index */
189  RexxString *name = (RexxString *)methodTable->index(i);
190  /* get the method */
191  RexxMethod *method = (RexxMethod *)methodTable->value(i);
192  ProtectedObject v;
193  /* run the method */
194  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
195  result->put((RexxObject *)v, name); /* add to the table */
196  }
197  }
198  return result->supplier(); /* convert this to a supplier */
199 }
200 
202 /******************************************************************************/
203 /* Function: Primitive level request('ARRAY') fast path */
204 /******************************************************************************/
205 {
206  if (isOfClass(Directory, this)) /* primitive level object? */
207  {
208  return this->makeArray(); /* just do the makearray */
209  }
210  else /* need to so full request mechanism */
211  {
212  return (RexxArray *)this->sendMessage(OREF_REQUEST, OREF_ARRAYSYM);
213  }
214 }
215 
217 /******************************************************************************/
218 /* Function: Create an array of all of the directory indices, including those*/
219 /* of all the SETMETHOD methods. */
220 /******************************************************************************/
221 {
222  return this->allIndexes();
223 }
224 
225 
226 /**
227  * Create an array of all of the directory indices, including those
228  * of all the SETMETHOD methods.
229  *
230  * @return An array containing all of the directory indices.
231  */
233 {
234  // get a result array of the appropriate size
235  wholenumber_t count = this->items();
236  RexxArray *result = (RexxArray *)new_array(count);
237  ProtectedObject p(result);
238  size_t out = 1;
239  // we're working directly off of the contents.
240  RexxHashTable *hashTab = this->contents;
241 
242  // traverse the entire table coping over the items.
243  for (HashLink i = hashTab->first(); hashTab->index(i) != OREF_NULL; i = hashTab->next(i))
244  {
245  RexxString *name = (RexxString *)hashTab->index(i);
246  result->put(name, out++);
247  }
248  // if e hae amethod table, we need to copy those indices also
249  if (this->method_table != OREF_NULL)
250  {
251  RexxTable *methodTable = this->method_table;
252  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i))
253  {
254  RexxString *name = (RexxString *)methodTable->index(i);
255  result->put(name, out++);
256  }
257  }
258  return result; /* send back the array */
259 }
260 
262 /******************************************************************************/
263 /* Function: Create an array of all of the directory values, including the */
264 /* values of all the SETMETHOD methods */
265 /******************************************************************************/
266 {
267  size_t count = this->items(); /* get the array size */
268  /* get result array of correct size */
269  RexxArray *result = (RexxArray *)new_array(count);
270  ProtectedObject p(result);
271  size_t i = 1; /* position in array */
272  RexxHashTable *hashTab = this->contents;
273  /* now traverse the entire table */
274  for (HashLink j = hashTab->first(); hashTab->index(j) != OREF_NULL; j = hashTab->next(j))
275  {
276  /* add to the array */
277  result->put(hashTab->value(j), i++);
278  }
279  /* have a method table? */
280  if (this->method_table != OREF_NULL)
281  {
282  RexxTable *methodTable = this->method_table; /* grab the table */
283  /* need to extract method values */
284  for (HashLink j = methodTable->first(); methodTable->available(j); j = methodTable->next(j))
285  {
286  /* get the directory index */
287  RexxString *name = (RexxString *)methodTable->index(j);
288  /* need to extract method values */
289  RexxMethod *method = (RexxMethod *)methodTable->value(j);
290  ProtectedObject v;
291  /* run the method */
292  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
293  result->put((RexxObject *)v, i++); /* add to the array */
294  }
295  }
296  return result; /* send back the array */
297 }
298 
300  RexxString *entryName) /* name to retrieve */
301 /******************************************************************************/
302 /* Function: This is the REXX version of entry. It issues a STRINGREQUEST*/
303 /* message to the entryname parameter if it isn't already a */
304 /* string or a name object. Thus, this may raise NOSTRING. */
305 /******************************************************************************/
306 {
307  /* get a string parameter (uppercase)*/
308  entryName = stringArgument(entryName, OREF_positional, ARG_ONE)->upper();
309  RexxObject *temp = this->at(entryName); /* retrieve the name */
310 
311  /* if we found nothing or the method */
312  if (temp == OREF_NULL) /* we ran returned nothing, */
313  {
314  temp = TheNilObject; /* return TheNilObject as a default */
315  }
316  return temp; /* return the value */
317 }
318 
320  RexxString *indexName) /* name to retrieve */
321 /******************************************************************************/
322 /* Function: Determine if the directory has an entry with this name (used */
323 /* without uppercasing) */
324 /******************************************************************************/
325 {
326  /* get as a string parameter */
327  indexName = stringArgument(indexName, OREF_positional, ARG_ONE);
328  /* got a value? */
329  if (this->contents->stringGet(indexName) != OREF_NULL)
330  {
331  return(RexxObject *)TheTrueObject;/* return true */
332  }
333  else
334  {
335  /* have a table? */
336  if (this->method_table != OREF_NULL)
337  {
338  /* look for a method */
339  RexxMethod *method = (RexxMethod *)this->method_table->stringGet(indexName);
340  if (method != OREF_NULL) /* have a method? */
341  {
342  /* then we have the index */
343  return(RexxObject *)TheTrueObject;
344  }
345  }
346  /* not in the directory */
347  return(RexxObject *)TheFalseObject;
348  }
349 }
350 
352  RexxString *entryName) /* name to retrieve */
353 /******************************************************************************/
354 /* Function: Determine if an entry exists in the directory (name will be */
355 /* upper cased) */
356 /******************************************************************************/
357 {
358  /* get as a string parameter */
359  entryName = stringArgument(entryName, OREF_positional, ARG_ONE)->upper();
360  /* in the table? */
361  if (this->contents->stringGet(entryName) != OREF_NULL)
362  {
363  return(RexxObject *)TheTrueObject;/* this is true */
364  }
365  else
366  {
367  /* have a table? */
368  if (this->method_table != OREF_NULL)
369  {
370  /* look for a method */
371  RexxMethod *method = (RexxMethod *)this->method_table->stringGet(entryName);
372  if (method != OREF_NULL) /* have a method? */
373  {
374  /* then we have the index */
375  return(RexxObject *)TheTrueObject;
376  }
377  }
378  /* not in the directory */
379  return(RexxObject *)TheFalseObject;
380  }
381 }
382 
384  RexxString *entryname, /* directory entry name */
385  RexxObject *entryobj) /* associated object */
386 /******************************************************************************/
387 /* Function: Add an entry to the directory (under an upper case name) */
388 /******************************************************************************/
389 {
390  /* get as a string parameter */
391  entryname = stringArgument(entryname, OREF_positional, ARG_ONE)->upper();
392  ProtectedObject p(entryname);
393  if (entryobj != OREF_NULL)
394  { /* have a new value? */
395  /* try to place in existing hashtab */
396  RexxHashTable *newHash = this->contents->stringPut(entryobj, entryname);
397  if (newHash != OREF_NULL) /* have a reallocation occur? */
398  {
399  /* hook on the new hash table */
400  OrefSet(this, this->contents, newHash);
401  }
402  if (this->method_table != OREF_NULL)
403  {
404  this->method_table->remove(entryname);
405  }
406  }
407  else
408  {
409  this->remove(entryname); /* remove this entry */
410  }
411  return OREF_NULL; /* don't return a value */
412 }
413 
414 
415 /**
416  * ooRexx exported version of the directory remove method.
417  *
418  * @param entryname The index name.
419  *
420  * @return The removed item. Returns .nil if the item did not exist
421  * in the directory.
422  */
424 {
425  /* get as a string parameter */
426  entryname = stringArgument(entryname, OREF_positional, ARG_ONE);
427  RexxObject *oldVal = remove(entryname);
428  if (oldVal == OREF_NULL)
429  {
430  oldVal = TheNilObject;
431  }
432  return oldVal;
433 }
434 
436  RexxString *entryname) /* name to retrieve */
437 /******************************************************************************/
438 /* Function: Remove an entry from a directory. */
439 /******************************************************************************/
440 {
441  RexxObject *oldVal = this->at(entryname); /* go get the directory value */
442  /* have a real entry? */
443  if (this->contents->stringGet(entryname) != OREF_NULL)
444  {
445  this->contents->remove(entryname); /* remove the entry */
446  }
447  /* if there's a method entry, remove that one too! */
448  /* have methods? */
449  if (this->method_table != OREF_NULL)
450  {
451  /* remove this method */
452  this->method_table->remove(entryname->upper());
453  }
454  return oldVal; /* return the directory value */
455 }
456 
458  RexxString *msgname, /* name of unknown message */
459  RexxArray *arguments, /* arguments to the message */
460  RexxDirectory *named_arguments)
461 /******************************************************************************/
462 /* Function: This is the REXX version of unknown. It invokes entry_rexx */
463 /* instead of entry, to ensure the proper error checking and */
464 /* return value handling is performed. */
465 /******************************************************************************/
466 {
467  /* validate the name */
468  RexxString *message_value = stringArgument(msgname, OREF_positional, ARG_ONE);
469  requiredArgument(arguments, OREF_positional, ARG_TWO); /* need an argument array */
470  /* get the length */
471  stringsizeC_t message_length = message_value->getCLength();
472  /* assignment form of access? */
473  if (message_length > 0 && message_value->getCharC(message_length - 1) == '=')
474  {
475  /* get this as an array */
476  arguments = (RexxArray *)REQUEST_ARRAY(arguments);
477  /* not an array item or a multiple */
478  /* dimension one, or more than one */
479  /* argument (CHM) */
480  if (arguments == TheNilObject || arguments->getDimension() != 1 || arguments->size() != 1 )
481  {
482  /* raise an error */
484  }
485  ProtectedObject p(arguments);
486 
487  // TODO named arguments: not used?
488 
489  /* extract the name part of the msg */
490  message_value = (RexxString *)message_value->extractC(0, message_length - 1);
491  /* do this as an assignment */
492  return this->setEntry(message_value, arguments->get(1));
493  }
494  else /* just a lookup form */
495  {
496  return this->entryRexx(message_value);
497  }
498 }
499 
501  RexxString *entryname, /* name to set this under */
502  RexxMethod *methodobj) /* new method argument */
503 /******************************************************************************/
504 /* Function: Add a method to the directory method table. */
505 /******************************************************************************/
506 {
507  /* get as a string parameter */
508  entryname = stringArgument(entryname, OREF_positional, ARG_ONE)->upper();
509  ProtectedObject p(entryname);
510  if (methodobj != OREF_NULL) /* have a method object? */
511  {
512  if (!isOfClass(Method, methodobj)) /* given as a string? */
513  {
514  /* convert to a method */
515  methodobj = RexxMethod::newMethodObject(entryname, methodobj, IntegerTwo, OREF_NULL);
516  /* set a new scope on this */
517  methodobj->setScope((RexxClass *)this);
518  }
519  else
520  {
521  /* set a new scope on this */
522  methodobj = methodobj->newScope((RexxClass *)this);
523  }
524  /* the unknown method? */
525  if (entryname->strCompare(CHAR_UNKNOWN))
526  {
527  /* stash this is a special place */
528  OrefSet(this, this->unknown_method, methodobj);
529  }
530  else
531  {
532  /* no table yet? */
533  if (this->method_table == OREF_NULL)
534  {
535  /* create one */
536  OrefSet(this, this->method_table, new_table());
537  }
538  /* now add the method */
539  this->method_table->stringPut(methodobj, entryname);
540  }
541  }
542  else
543  {
544  /* the unknown method? */
545  if (entryname->strCompare(CHAR_UNKNOWN))
546  {
547  /* cast off the unknown method */
548  OrefSet(this, this->unknown_method, OREF_NULL);
549  }
550  else
551  {
552  /* if we have a table */
553  if (this->method_table != OREF_NULL)
554  {
555  /* remove this entry */
556  this->method_table->remove(entryname);
557  }
558  }
559  }
560  this->contents->remove(entryname); /* remove any table entry */
561  return OREF_NULL; /* this always returns nothing */
562 }
563 
565  RexxObject *_value, /* value to add */
566  RexxObject *_index) /* index to use */
567 /******************************************************************************/
568 /* Function: Merge a single item during merge processing */
569 /******************************************************************************/
570 {
571  /* just add the item */
572  return this->put(_value, (RexxString *)_index);
573 }
574 
576  RexxString *_index) /* index to retrieve */
577 /******************************************************************************/
578 /* Function: Retrieve an item from a directory */
579 /******************************************************************************/
580 {
581  /* try to retrieve the value */
582  RexxObject *result = this->contents->stringGet(_index);
583  if (result == OREF_NULL)
584  { /* no value? */
585  /* have a table? */
586  if (this->method_table != OREF_NULL)
587  {
588  /* look for a method */
589  RexxMethod *method = (RexxMethod *)this->method_table->stringGet(_index);
590  if (method != OREF_NULL) /* have a method? */
591  {
592  ProtectedObject v;
593  /* run the method */
594  method->run(ActivityManager::currentActivity, this, _index, NULL, 0, 0, v);
595  return(RexxObject *)v;
596 
597  }
598  }
599  /* got an unknown method? */
600  if (this->unknown_method != OREF_NULL)
601  {
602  RexxObject *arg = _index;
603  RexxObject *args[1];
604  args[0] = _index; // positional argument
605  ProtectedObject v;
606  /* run it */
607  this->unknown_method->run(ActivityManager::currentActivity, this, OREF_UNKNOWN, args, 1, 0, v);
608  return(RexxObject *)v;
609  }
610  }
611  return result; /* return a result */
612 }
613 
615  RexxString *_index) /* index to retrieve */
616 /******************************************************************************/
617 /* Function: This is the REXX version of at. It issues a */
618 /* STRINGREQUEST message to the index parameter if it isn't */
619 /* already a string or a name object. Thus, this may raise */
620 /* NOSTRING. */
621 /******************************************************************************/
622 {
623  RexxObject *temp; /* Temporary holder for return value */
624 
625  /* get as a string parameter */
626  _index = stringArgument(_index, OREF_positional, ARG_ONE);
627  // is this the .local object? We'll need to check with the security manager
628  if (ActivityManager::getLocal() == this)
629  {
631  temp = manager->checkLocalAccess(_index);
632  if (temp != OREF_NULL)
633  {
634  return temp;
635  }
636  }
637  temp = this->at(_index); /* run real AT */
638  /* if we found nothing or the method */
639  if (temp == OREF_NULL) /* we ran returned nothing */
640  {
641  temp = TheNilObject; /* return TheNilObject as a default */
642  }
643  return temp; /* return the value */
644 }
645 
647  RexxObject *_value, /* value to add */
648  RexxString *_index) /* string index of the value */
649 /******************************************************************************/
650 /* Function: Add an item to a directory */
651 /******************************************************************************/
652 {
653  /* get as a string parameter */
654  _index = stringArgument(_index, OREF_positional, ARG_TWO);
655  ProtectedObject p(_index);
656  if (this->method_table != OREF_NULL) /* have a table? */
657  {
658  this->method_table->remove(_index);/* remove any method */
659  }
660  /* try to place in existing hashtab */
661  RexxHashTable *newHash = this->contents->stringPut(_value, _index);
662  if (newHash != OREF_NULL) /* have a reallocation occur? */
663  {
664  /* hook on the new hash table */
665  OrefSet(this, this->contents, newHash);
666  }
667  return OREF_NULL; /* this returns nothing */
668 }
669 
671 /******************************************************************************/
672 /* Function: Reset a directory to a "pristine" empty state */
673 /******************************************************************************/
674 {
675  // empty the hashtables without reallocating.
676  contents->empty();
677  if (method_table != OREF_NULL)
678  {
679  method_table->empty();
680  }
681  // clear out the unknown method.
682  OrefSet(this, this->unknown_method, OREF_NULL);
683 }
684 
685 
686 /**
687  * Empty a hash table collection.
688  *
689  * @return nothing
690  */
692 {
693  reset();
694  return OREF_NULL;
695 }
696 
697 
698 /**
699  * Test if a HashTableCollection is empty.
700  *
701  * @return
702  */
704 {
705  return items() == 0 ? TheTrueObject : TheFalseObject;
706 }
707 
708 
709 
710 /**
711  * Retrieve an index for a given item. Which index is returned
712  * is indeterminate.
713  *
714  * @param target The target object.
715  *
716  * @return The index for the target object, or .nil if no object was
717  * found.
718  */
720 {
721  // required argument
722  requiredArgument(target, OREF_positional, ARG_ONE);
723  // retrieve this from the hash table
724  RexxObject *result = this->contents->getIndex(target);
725  // not found, return .nil
726  if (result == OREF_NULL)
727  {
728  // rats, we might need to do this the hardway
729  if (this->method_table != OREF_NULL)
730  {
731  RexxTable *methodTable = this->method_table;
732 
733  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i))
734  {
735  // we need to run each method, looking for a value that matches
736  RexxString *name = (RexxString *)methodTable->index(i);
737  RexxMethod *method = (RexxMethod *)methodTable->value(i);
738  ProtectedObject v;
739  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
740  // got a match?
741  if (target->equalValue((RexxObject *)v))
742  {
743  return name; // the name is the index
744  }
745  }
746  }
747  return TheNilObject; // the nil object is the unknown index
748  }
749  return result;
750 }
751 
752 
753 /**
754  * Test if a given item exists in the collection.
755  *
756  * @param target The target object.
757  *
758  * @return .true if the object exists, .false otherwise.
759  */
761 {
762  requiredArgument(target, OREF_positional, ARG_ONE);
763  // the lookup is more complicated, so just delegate to the index lookup code.
764  return indexRexx(target) != TheNilObject ? TheTrueObject : TheFalseObject;
765 }
766 
767 
768 /**
769  * Remove a given item from the collection.
770  *
771  * @param target The target object.
772  *
773  * @return .true if the object exists, .false otherwise.
774  */
776 {
777  requiredArgument(target, OREF_positional, ARG_ONE);
778  // the lookup is more complicated, so just delegate to the index lookup code.
779  RexxObject *i = indexRexx(target);
780  // just use the retrieved index to remove.
781  if (i != TheNilObject)
782  {
783  return remove((RexxString *)i);
784  }
785  return TheNilObject; // nothing removed.
786 }
787 
789  RexxObject **init_args,
790  size_t argCount,
791  size_t named_argCount)
792 /******************************************************************************/
793 /* Function: Create a new directory for a REXX program */
794 /******************************************************************************/
795 {
796  /* get a new directory */
797  /* NOTE: this does not use the */
798  /* macro version because the class */
799  /* object might actually be for a */
800  /* subclass */
801  RexxDirectory *newDirectory = new_directory();
802  ProtectedObject p(newDirectory);
803  newDirectory->setBehaviour(((RexxClass *)this)->getInstanceBehaviour());
804  /* does object have an UNINT method */
805  if (((RexxClass *)this)->hasUninitDefined())
806  {
807  newDirectory->hasUninit(); /* Make sure everyone is notified. */
808  }
809  /* call any rexx level init's */
810  newDirectory->sendMessage(OREF_INIT, init_args, argCount, named_argCount);
811  return newDirectory; /* return the new directory */
812 }
813 
815 /******************************************************************************/
816 /* Create a new directory item */
817 /******************************************************************************/
818 {
819  /* get a new object and hash */
821 }
822 
823 /**
824  * Helper for named arguments.
825  * Create a new directory from an array of(index1, item1, index2, item2, ...)
826  * When count = 0, no directory is created, returns OREF_NULL.
827  *
828  * @return A directory
829  */
831 {
832  if (count == 0) return OREF_NULL;
833 
834  RexxDirectory *directory = new_directory();
835  ProtectedObject p(directory);
836 
837  for (size_t i = 0; i < (2 * count); i+=2) /* loop through the index,item list */
838  {
839  RexxObject *index = arglist[i];
840  RexxObject *item = arglist[i+1];
841  directory->put(item, REQUEST_STRING(index));
842  }
843 
844  return directory;
845 }
846 
847 
848 /**
849  * Helper for named arguments.
850  * Create an array of all of the directory indices &items, including those
851  * of all the SETMETHOD methods.
852  *
853  * @return An array containing all of the directory indices & items: index1, item1, index2, item2, ...
854  */
856 {
857  // get a result array of the appropriate size
858  size_t count = this->items();
859  RexxArray *result = (RexxArray *)new_array(2 * count);
860  ProtectedObject p(result);
861  size_t out = 1;
862  // we're working directly off of the contents.
863  RexxHashTable *hashTab = this->contents;
864 
865  // traverse the entire table coping over the items.
866  for (HashLink i = hashTab->first(); hashTab->index(i) != OREF_NULL; i = hashTab->next(i))
867  {
868  result->put(hashTab->index(i), out++);
869  result->put(hashTab->value(i), out++);
870  }
871  // if has a method table, we need to copy those indices also
872  if (this->method_table != OREF_NULL)
873  {
874  RexxTable *methodTable = this->method_table;
875  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i))
876  {
877  RexxString *name = (RexxString *)methodTable->index(i);
878  result->put(name, out++);
879 
880  RexxMethod *method = (RexxMethod *)methodTable->value(i);
881  ProtectedObject v;
882  /* run the method */
883  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
884  result->put((RexxObject *)v, out++); /* add to the array */
885  }
886  }
887  return result; /* send back the array */
888 }
889 
890 
891 /**
892  * Helper for named arguments.
893  * Push on the stack all the directory indices &items, including those
894  * of all the SETMETHOD methods: index1, item1, index2, item2, ...
895  *
896  * @return The count of pushed pairs index & item (= this->items())
897  */
899 {
900  size_t out = 0;
901  // we're working directly off of the contents.
902  RexxHashTable *hashTab = this->contents;
903 
904  // traverse the entire table coping over the items.
905  for (HashLink i = hashTab->first(); hashTab->index(i) != OREF_NULL; i = hashTab->next(i), out++)
906  {
907  stack->push(hashTab->index(i));
908  stack->push(hashTab->value(i));
909  }
910  // if has a method table, we need to copy those indices also
911  if (this->method_table != OREF_NULL)
912  {
913  RexxTable *methodTable = this->method_table;
914  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i), out++)
915  {
916  RexxString *name = (RexxString *)methodTable->index(i);
917  stack->push(name);
918 
919  RexxMethod *method = (RexxMethod *)methodTable->value(i);
920  ProtectedObject v;
921  /* run the method */
922  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
923  stack->push(v);
924  }
925  }
926  return out;
927 }
928 
929 
930 /**
931  * Helper for named arguments.
932  * Append to the array all the directory indices &items, including those
933  * of all the SETMETHOD methods: index1, item1, index2, item2, ...
934  *
935  * from: at which position to start storing using the method array.put.
936  * CAREFUL! 1-based, so NEVER pass 0.
937  *
938  * @return The count of appended pairs index & item (= this->items())
939  */
941 {
942  size_t out = 0;
943  // we're working directly off of the contents.
944  RexxHashTable *hashTab = this->contents;
945 
946  // traverse the entire table coping over the items.
947  for (HashLink i = hashTab->first(); hashTab->index(i) != OREF_NULL; i = hashTab->next(i), out++)
948  {
949  array->put(hashTab->index(i), from++);
950  array->put(hashTab->value(i), from++);
951  }
952  // if has a method table, we need to copy those indices also
953  if (this->method_table != OREF_NULL)
954  {
955  RexxTable *methodTable = this->method_table;
956  for (HashLink i = methodTable->first(); methodTable->available(i); i = methodTable->next(i), out++)
957  {
958  RexxString *name = (RexxString *)methodTable->index(i);
959  array->put(name, from++);
960 
961  RexxMethod *method = (RexxMethod *)methodTable->value(i);
962  ProtectedObject v;
963  /* run the method */
964  method->run(ActivityManager::currentActivity, this, name, NULL, 0, 0, v);
965  array->put(v, from++);
966  }
967  }
968  return out;
969 }
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Directory
RexxDirectory * new_directory()
RexxInteger * new_integer(wholenumber_t v)
#define OREF_NULL
Definition: RexxCore.h:60
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:469
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:283
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheTrueObject
Definition: RexxCore.h:186
const int ARG_TWO
Definition: RexxCore.h:81
#define IntegerTwo
Definition: RexxCore.h:191
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
const int ARG_ONE
Definition: RexxCore.h:80
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:291
#define Error_Incorrect_method_noarray
size_t HashLink
RexxTable * new_hashCollection(size_t s, size_t s2, size_t t)
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:493
#define CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
#define cleanUpFlatten
Definition: RexxMemory.hpp:479
#define setUpFlatten(type)
Definition: RexxMemory.hpp:473
RexxTable * new_table()
Definition: TableClass.hpp:76
static RexxDirectory * getLocal()
static RexxActivity *volatile currentActivity
SecurityManager * getEffectiveSecurityManager()
size_t getDimension()
Definition: ArrayClass.cpp:693
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxObject * hasItem(RexxObject *)
RexxArray * allIndexes()
RexxObject * setMethod(RexxString *, RexxMethod *)
RexxObject * copy()
RexxObject * unflatten(RexxEnvelope *)
void liveGeneral(int reason)
RexxObject * indexRexx(RexxObject *)
RexxArray * requestArray()
RexxArray * allItems()
RexxObject * at(RexxString *)
RexxObject * setEntry(RexxString *, RexxObject *)
RexxObject * removeItem(RexxObject *)
RexxObject * mergeItem(RexxObject *, RexxObject *)
RexxObject * hasEntry(RexxString *)
size_t pushAllIndexesItemsTo(RexxExpressionStack *stack)
RexxObject * put(RexxObject *, RexxString *)
void live(size_t)
RexxArray * allIndexesItems(void)
RexxObject * isEmpty()
RexxObject * newRexx(RexxObject **init_args, size_t, size_t)
size_t appendAllIndexesItemsTo(RexxArray *array, size_t from)
RexxSupplier * supplier()
static RexxDirectory * newInstance()
RexxObject * empty()
void flatten(RexxEnvelope *)
RexxObject * atRexx(RexxString *)
RexxObject * entryRexx(RexxString *)
RexxArray * makeArray()
RexxMethod * unknown_method
RexxObject * unknown(RexxString *, RexxArray *, RexxDirectory *)
static RexxDirectory * fromIndexItemArray(RexxObject **arglist, size_t count)
RexxObject * itemsRexx()
RexxTable * method_table
static void createInstance()
RexxObject * hasIndex(RexxString *)
RexxObject * entry(RexxString *)
RexxObject * remove(RexxString *)
static RexxClass * classInstance
RexxObject * removeRexx(RexxString *)
void addTable(RexxObject *obj)
void push(RexxObject *value)
bool available(HashLink pos)
RexxObject * value(HashLink pos)
HashLink next(HashLink pos)
void liveGeneral(int reason)
virtual RexxObject * remove(RexxObject *key)
RexxHashTable * contents
RexxObject * index(HashLink pos)
RexxSupplier * supplier()
virtual RexxObject * put(RexxObject *, RexxObject *)
RexxObject * getIndex(RexxObject *value)
RexxHashTable * stringPut(RexxObject *value, RexxString *key)
RexxObject * index(HashLink position)
HashLink first()
RexxObject * remove(RexxObject *key)
RexxObject * value(HashLink position)
RexxObject * stringGet(RexxString *key)
size_t totalEntries()
HashLink next(HashLink position)
void setBehaviour(RexxBehaviour *b)
void run(RexxActivity *, RexxObject *, RexxString *, RexxObject **, size_t, size_t, ProtectedObject &)
void setScope(RexxClass *)
static RexxMethod * newMethodObject(RexxString *, RexxObject *, RexxObject *, RexxSource *a, bool isBlock=false)
RexxMethod * newScope(RexxClass *)
bool equalValue(RexxObject *other)
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxString * extractC(sizeC_t offset, sizeC_t sublength)
sizeC_t getCLength()
bool strCompare(const char *s)
codepoint_t getCharC(sizeC_t p)
RexxString * upper()
RexxObject * stringPut(RexxObject *, RexxString *)
Definition: TableClass.cpp:113
RexxObject * stringGet(RexxString *key)
Definition: TableClass.hpp:67
RexxObject * checkLocalAccess(RexxString *index)
stringsize_t stringsizeC_t
Definition: rexx.h:241
ssize_t wholenumber_t
Definition: rexx.h:230