ArrayClass.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 Array Class */
42 /* */
43 /* */
44 /* This Array class functions in two ways. One as an auto-extending array */
45 /* and as a static array. The static methods are used inside the kernel */
46 /* since we always know the exact size of the array we want and will place */
47 /* those elements into the array, so the static sized methods are optimized. */
48 /* */
49 /* The auto-extending methods are for the OREXX level behaviour. They */
50 /* may also be used inside the kernel if that behaviour is required. */
51 /* */
52 /* Any of the methods can be used on an array. The behaviour of an array */
53 /* depends on the methods used on the array, since there is only one type */
54 /* of array object, and its data is the same irreguardless of the methods */
55 /* used on it. */
56 /* */
57 /* Object creation functions: */
58 /* new_array(s) - Create an array of size s, initial size of array is */
59 /* set to s. This array will be used as a static array */
60 /* new_array(a1) - Create array of size 1 and put a1 in it. */
61 /* same as an array~of(a1) */
62 /* new_array(a1,a2) - Create array of size 2 and put a1 and a2 in it */
63 /* same as an array~of(a1,a2) */
64 /* new_array(a1, a2, a3) Same as new_array2 but 3 elements. */
65 /* new_array(a1, a2, a3, a4) " " " " 4 " */
66 /* */
67 /* */
68 /******************************************************************************/
69 #include <stdlib.h>
70 #include "RexxCore.h"
71 #include "RexxActivity.hpp"
72 #include "IntegerClass.hpp"
73 #include "SupplierClass.hpp"
74 #include "ArrayClass.hpp"
75 #include "MutableBufferClass.hpp"
76 #include "ActivityManager.hpp"
77 #include "ProtectedObject.hpp"
78 
79 #include <deque>
80 
81 // std::min(...) raises error '(': illegal token on right side of '::'
82 #define min(a,b) (a<=b?a:b)
83 
84 // singleton class instance
87 
89 const size_t RexxArray::ARRAY_MIN_SIZE = 4;
90 const size_t RexxArray::ARRAY_DEFAULT_SIZE = 10; // we use a larger default for ooRexx allocated arrays
91 
92 /**
93  * Create initial class object at bootstrap time.
94  */
96 {
97  CLASS_CREATE(Array, "Array", RexxClass);
98  nullArray = new_array((size_t)0); /* set up a null array */
99 }
100 
101 
102 /**
103  * Initialize an array
104  *
105  * @param _size The initial size of the array.
106  * @param maxSize The maximum size this array can hold (maxSize >= size)
107  */
108 void RexxArray::init(size_t _size, size_t maxSize)
109 {
110  this->arraySize = _size;
111  this->maximumSize = maxSize;
112  this->lastElement = 0; // no elements set yet
113  /* no expansion yet, use ourself */
114  OrefSet(this, this->expansionArray, this);
115 }
116 
117 /**
118  * Copy the array (and the expansion array, if necessary)
119  *
120  * @return A copy of the array object.
121  */
123 /******************************************************************************/
124 /* Function: create a copy of array and expansion array. */
125 /******************************************************************************/
126 {
127  /* make a copy of ourself */
128  RexxArray *newArray = (RexxArray *) this->RexxObject::copy();
129  ProtectedObject p(newArray);
130  /* this array contain the data? */
131  if (this->expansionArray != OREF_NULL && this->expansionArray != this)
132  {
133  /* no, make sure we get a copy of */
134  /* array containing data. */
135  newArray->setExpansion(this->expansionArray->copy());
136  }
137  else
138  {
139  /* no, make sure we get a copy of */
140  /* array containing data. */
141  newArray->setExpansion(newArray); /* make sure we point to ourself! */
142  }
143  return(RexxObject *)newArray; /* return the new array */
144 }
145 
146 void RexxArray::live(size_t liveMark)
147 /******************************************************************************/
148 /* Function: Normal garbage collection live marking */
149 /******************************************************************************/
150 {
151  RexxObject **arrayPtr;
152  RexxObject **endPtr;
153 
154  memory_mark(this->dimensions);
155  memory_mark(this->objectVariables);
156  /* mark expanded array */
158  for (arrayPtr = this->objects, endPtr = arrayPtr + this->arraySize; arrayPtr < endPtr; arrayPtr++)
159  {
160  memory_mark(*arrayPtr);
161  }
162 }
163 
164 void RexxArray::liveGeneral(int reason)
165 /******************************************************************************/
166 /* Function: Generalized object marking */
167 /******************************************************************************/
168 {
170  memory_mark_general(this->objectVariables);
172 
173  for (RexxObject **arrayPtr = this->objects; arrayPtr < this->objects + this->arraySize; arrayPtr++)
174  {
175  memory_mark_general(*arrayPtr);
176  }
177 }
178 
180 /******************************************************************************/
181 /* Function: Flatten an object */
182 /******************************************************************************/
183 {
185 
186  flatten_reference(newThis->dimensions, envelope);
187  flatten_reference(newThis->objectVariables, envelope);
188  flatten_reference(newThis->expansionArray, envelope);
189  for (size_t i = 0; i < this->arraySize; i++)
190  {
191  flatten_reference(newThis->objects[i], envelope);
192  }
193 
195 }
196 
197 
198 /**
199  * Place an object into the array.
200  * JLF:
201  * ooRexx4 doesn't check if there is sufficient space, it's up to the caller to check that.
202  * I added the call 'ensureSpace(pos)' to ensure there is sufficient space.
203  * ooRexx5 does the same, so...
204  *
205  * @param eref The object to add.
206  * @param pos The index of the added item (origin 1)
207  */
208 void RexxArray::put(RexxObject * eref, size_t pos)
209 {
210  this->ensureSpace(pos);
211  OrefSet(this->expansionArray, (this->data())[pos - 1], eref);
212  // check the last set element
213  if (pos > lastElement)
214  {
215  lastElement = pos;
216  }
217 }
218 
219 /**
220  * The Rexx stub for the Array PUT method. This does full
221  * checking for the array.
222  *
223  * @param arguments The array of all arguments sent to the method (variable arguments allowed here.)
224  * @param argCount The number of arguments in the method call.
225  *
226  * @return Always return nothing.
227  */
228 RexxObject *RexxArray::putRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
229 {
230  size_t position; /* array position */
231 
232  RexxObject *value = arguments[0]; /* get the value to assign */
233  /* no real value? */
234  if (argCount == 0 || value == OREF_NULL)
235  {
236  /* this is an error */
237  missingArgument(OREF_positional, ARG_ONE); /* this is an error */
238  }
239  /* go validate the index */
240  /* have array expanded if necessary */
241  this->validateIndex(arguments + 1, argCount - 1, 2, RaiseBoundsInvalid | ExtendUpper | RaiseBoundsTooMany, position);
242 
243  this->put(value, position); /* set the new value */
244  return OREF_NULL; /* Make sure RESULT gets dropped */
245 }
246 
247 
248 /**
249  * Fill all locations of the array with the given object
250  *
251  * @return No return value.
252  */
254 {
255  requiredArgument(value, OREF_positional, ARG_ONE);
256  // sigh, we have to use OrefSet
257  for (size_t i = 0; i < this->size(); i++)
258  {
259 
260  OrefSet(this, this->objects[i], value);
261  }
262  // the last element is now the size one
263  lastElement = size();
264  return OREF_NULL; // no real return value
265 }
266 
267 
268 /**
269  * Empty all of the items from an array.
270  *
271  * @return No return value.
272  */
274 {
275  // if not working with an oldspace object (VERY likely), we can just use memset to clear
276  // everything.
277  if (this->isNewSpace())
278  {
279  memset(this->data(), '\0', sizeof(RexxObject *) * this->size());
280  }
281  else
282  {
283  // sigh, we have to use OrefSet
284  for (size_t i = 0; i < this->size(); i++)
285  {
286 
287  OrefSet(this, this->objects[i], OREF_NULL);
288  }
289  }
290  // no element set yet
291  lastElement = 0;
292  return OREF_NULL; // no real return value
293 }
294 
295 
296 /**
297  * Test if an array is empty.
298  *
299  * @return True if the array is empty, false otherwise
300  */
302 {
303  return (items() == 0) ? TheTrueObject : TheFalseObject;
304 }
305 
306 
307 /**
308  * Append an item after the last item in the array.
309  *
310  * @param value The value to append.
311  *
312  * @return The index of the appended item.
313  */
315 {
316  requiredArgument(value, OREF_positional, ARG_ONE);
317 
318  // this is not intended for multi-dimensional arrays since they can't expand
319  if (isMultiDimensional())
320  {
322  }
323 
324  size_t newIndex = lastElement + 1;
325 
326  ensureSpace(newIndex);
327  put(value, newIndex);
328  return new_integer(newIndex);
329 }
330 
331 
332 /**
333  * Insert an element into the given index location.
334  *
335  * @param _value The value to insert. This can be omitted, which will
336  * insert an empty slot at the indicated position.
337  * @param index The target index. This can be .nil, which will insert
338  * at the beginning, omitted, which will insert at the end,
339  * or a single-dimensional index of the position where the
340  * value will be inserted after.
341  *
342  * @return The index of the inserted valued.
343  */
345 {
346  /* multidimensional array? */
347  if (isMultiDimensional())
348  {
349  /* this is an error */
351  }
352 
353  size_t position; // array position
354 
355  if (index == TheNilObject)
356  {
357  position = 1; // the insertion point of the item is 1
358  }
359  else if (index == OREF_NULL)
360  {
361  position = size() + 1; // inserting after the last item
362  }
363  else
364  {
365  // validate the index and expand if necessary.
366  this->validateIndex(&index, 1, 2, RaiseBoundsInvalid | RaiseBoundsTooMany, position);
367  position = position + 1; // we insert AFTER the given index, so bump this
368  }
369 
370  // do the actual insertion
371  return new_integer(insert(_value, position));
372 }
373 
374 
375 /**
376  * Delete an element from the given index location, shifting the
377  * item indexes as required.
378  *
379  * @param index The target index. This can be a single number or an array
380  * containing a single number.
381  *
382  * @return The object that has been deleted. Returns .nil if the
383  * target index does not exist.
384  */
386 {
387  /* multidimensional array? */
388  if (isMultiDimensional())
389  {
390  /* this is an error */
392  }
393 
394  size_t position; // array position
395 
396  // validate the index and expand if necessary.
397  this->validateIndex(&index, 1, 1, RaiseBoundsInvalid | RaiseBoundsTooMany, position);
398 
399  // do the actual insertion
400  return deleteItem(position);
401 }
402 
403 
404 /**
405  * Open a gap in the array by shifting each element to the right
406  * starting at the given index.
407  *
408  * @param index The index of the first item to shift.
409  *
410  * @param elements The number of elements to shift.
411  */
412 void RexxArray::openGap(size_t index, size_t elements)
413 {
414  // is this larger than our current size? If so, we have nothing to move
415  // but do need to expand the array size to accommodate the additional members
416  if (index > size())
417  {
418  ensureSpace(index + elements - 1);
419  }
420  else {
421  // make sure we have space for the additional elements
422  ensureSpace(size() + elements);
423 
424  char *_end = (char *)slotAddress(this->lastElement + 1);
425  char *_start = (char *)slotAddress(index);
426  char *_target = (char *)slotAddress(index + elements);
427  /* shift the array over */
428  memmove(_target, _start, _end - _start);
429 
430  // now null out all of the slots in the gap, using an
431  // explicit assignment rather than put to avoid old-to-new
432  // tracking issues
433  for (size_t i = index - 1; i < index + elements - 1; i++)
434  {
435  this->data()[i] = OREF_NULL;
436  }
437  lastElement += elements; // the position of the last element has now moved.
438  }
439 }
440 
441 /**
442  * Close a gap in the array item.
443  *
444  * @param index The gap to close.
445  * @param elements The size of the gap to close.
446  */
447 void RexxArray::closeGap(size_t index, size_t elements)
448 {
449  // if we're beyond the current size, nothing to do
450  if (index > size())
451  {
452  return;
453  }
454 
455  // cap the number of elements we're shifting.
456  elements = Numerics::minVal(elements, lastElement - index + 1);
457 
458  // explicitly null out the slots of the gap we're closing to
459  // ensure that any oldspace tracking issues are resolved. This
460  // explicitly uses put() to make sure this is done.
461  for (size_t i = index; i < index + elements; i++)
462  {
463  put(OREF_NULL, i);
464  }
465  /* get the address of first element */
466  char *_target = (char *)slotAddress(index);
467  char *_start = (char *)slotAddress(index + elements);
468  // and the end location of the real data
469  char *_end = (char *)slotAddress(lastElement + 1);
470  /* shift the array over */
471  memmove(_target, _start, _end - _start);
472  // adjust the last element position
473  lastElement -= elements;
474  shrink(elements); // adjust the size downward
475 }
476 
477 
478 /**
479  * Append an item after the last item in the array.
480  *
481  * @param value The value to append.
482  *
483  * @return The index of the appended item.
484  */
486 {
487  size_t newIndex = lastElement + 1;
488 
489  ensureSpace(newIndex);
490  put(value, newIndex);
491  return newIndex;
492 }
493 
494 
495 
496 /**
497  * The Rexx stub for the Array GET method. This does full
498  * checking for the array.
499  *
500  * @param arguments The array of all arguments sent to the method (variable arguments allowed here.)
501  * @param argCount The number of arguments in the method call.
502  *
503  * @return Value at the provided index or .nil if the item does
504  * not exist.
505  */
506 RexxObject *RexxArray::getRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
507 {
508  size_t position; /* array position */
509  RexxObject * _result; /* returned result */
510 
511  /* go validate the index */
512  if (!this->validateIndex(arguments, argCount, 1, RaiseBoundsTooMany | RaiseBoundsInvalid, position))
513  {
514  _result = TheNilObject; /* just return .nil */
515  }
516  else
517  { /* return that element */
518  _result = *(this->data() + position - 1);
519  if (_result == OREF_NULL) /* no object there? */
520  {
521  _result = TheNilObject; /* just return .nil */
522  }
523  }
524  return _result; /* return the result */
525 }
526 
527 
528 /**
529  * Get an item from the array, with array size sensitivity.
530  *
531  * @param position The target position.
532  *
533  * @return The object at the array position. Returns OREF_NULL if there
534  * is not item at that position.
535  */
536 RexxObject *RexxArray::getApi(size_t position)
537 {
538  /* out of bounds? */
539  if (position > this->size())
540  {
541  return OREF_NULL;
542  }
543  return get(position);
544 }
545 
546 
547 /**
548  * Put an array item into an array on behalf of an API. This will
549  * extend the array, if necessary, to accomodate the put.
550  *
551  * @param o The inserted object.
552  * @param position The target position.
553  */
554 void RexxArray::putApi(RexxObject *o, size_t position)
555 {
556  /* out of bounds? */
557  if (position > this->size())
558  {
559  if (position >= MAX_FIXEDARRAY_SIZE)
560  {
562  }
563  this->extend(position - this->size());
564  }
565  put(o, position);
566 }
567 
568 
569 /**
570  * Determine if an item exists for a given index position.
571  *
572  * @param i The target index.
573  *
574  * @return Either true or false, depending on whether the item exists.
575  */
577 /******************************************************************************/
578 /* Function: Determine if an element exist for a position */
579 /******************************************************************************/
580 {
581  /* in bounds and here? */
582  if (i > 0 && i <= this->size() && *(this->data()+i-1) != OREF_NULL)
583  {
584  return true; /* this is true */
585  }
586  else
587  {
588  return false; /* nope, don't have it */
589  }
590 }
591 
592 
594 /******************************************************************************/
595 /* Function: Remove an item from the array */
596 /******************************************************************************/
597 {
598  RexxObject *result; /* removed object */
599 
600  /* within the bounds? */
601  if (_index > 0 && _index <= this->size() && *(this->data() + _index - 1) != OREF_NULL)
602  {
603  /* get the item */
604  result = *(this->data() + _index - 1);
605  /* clear it out */
606  OrefSet(this->expansionArray, *(this->data() + _index - 1), OREF_NULL);
607  // if we removed the last element, we need to scan backwards to find
608  // the last one
609  if (_index == lastElement)
610  {
611  // back off at least one position, then scan for the new last one
612  lastElement--;
613  while (lastElement != 0 && *(this->data() + lastElement - 1) == OREF_NULL)
614  {
615  lastElement--;
616  }
617  }
618  return result; /* and return */
619  }
620  else
621  {
622  return OREF_NULL; /* return nothing */
623  }
624 }
625 
626 RexxObject *RexxArray::removeRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
627 /******************************************************************************/
628 /* Function: Remove an item from the array and return the item. .nil */
629 /* is returned if the item does not exist */
630 /******************************************************************************/
631 {
632  RexxObject *result; /* returned result */
633  size_t position; /* array position */
634 
635  /* go validate the index */
636  if (!this->validateIndex(arguments, argCount, 1, RaiseBoundsTooMany | RaiseBoundsInvalid, position))
637  {
638  result = TheNilObject; /* yup, return .nil. */
639  }
640  else
641  {
642  /* get the current element */
643  result = *(this->data() + position - 1);
644  /* remove the item from the array */
645  OrefSet(this->expansionArray, *(this->data() + position - 1), OREF_NULL);
646  if (position == lastElement)
647  {
648  // back off at least one position, then scan for the new last one
649  lastElement--;
650  while (lastElement != 0 && *(this->data() + lastElement - 1) == OREF_NULL)
651  {
652  lastElement--;
653  }
654  }
655  if (result == OREF_NULL) /* no existing value? */
656  {
657  result = TheNilObject; /* return .nil instead */
658  }
659  }
660  return result; /* return this value */
661 }
662 
664 /******************************************************************************/
665 /* Function: Return count of actual items in an array */
666 /******************************************************************************/
667 {
668  size_t count; /* actual count of items in array */
669  RexxArray *realArray; /* array item pointer */
670 
671  count = 0; /* no items yet */
672  realArray = this->expansionArray; /* Get array with data */
673  /* loop through all array items */
674  for (size_t i = 0; i < realArray->arraySize; i++)
675  {
676  /* have a real item here? */
677  if (realArray->objects[i] != OREF_NULL)
678  {
679  count++; /* bump the item counter */
680  }
681  }
682  return count; /* return the count object */
683 }
684 
686 /******************************************************************************/
687 /* Function: Return count of actual items in an array */
688 /******************************************************************************/
689 {
690  return new_integer(items());
691 }
692 
694 /******************************************************************************/
695 /* Function: Query array dimension information */
696 /******************************************************************************/
697 {
698  if (this->dimensions == OREF_NULL) /* no dimensions array? */
699  {
700  return 1; /* one dimension array */
701  }
702  else
703  {
704  return this->dimensions->size(); /* return size of dimensions array */
705  }
706 }
707 
708 /**
709  * Return an array of the dimensions of this array.
710  *
711  * @return An array item with one size item for each dimension of the
712  * array.
713  */
715 {
716  // if it is a single dimension array, return an array with the size
717  // as a single item
718  if (isSingleDimensional())
719  {
720  return new_array(new_integer(this->size()));
721  }
722  else
723  {
724  // return a copy of the dimensions array
725  return this->dimensions->copy();
726  }
727 }
728 
729 RexxObject *RexxArray::dimension( /* query dimensions of an array */
730  RexxObject *target) /* dimension to query */
731 /******************************************************************************/
732 /* Function: Query array dimension information */
733 /******************************************************************************/
734 {
735  if (target == OREF_NULL)
736  { /* non-specific query? */
737  if (this->dimensions == OREF_NULL)
738  {
739  if (this->size() == 0)
740  {
741  /* unknown dimension */
742  return IntegerZero;
743  }
744  else
745  {
746  /* one dimension array */
747  return IntegerOne;
748  }
749  }
750  else
751  { /* return size of dimensions array */
752  return new_integer(this->dimensions->size());
753  }
754  }
755  else
756  {
757  /* convert to a number */
758  size_t position = target->requiredPositive(OREF_positional, ARG_ONE);
759  /* asking for dimension of single? */
760  if (isSingleDimensional())
761  {
762  if (position == 1)
763  { /* first dimension? */
764  /* just give back the size */
765  return new_integer(this->size());
766  }
767  else
768  {
769  /* no size in this dimension */
770  return IntegerZero;
771  }
772  }
773  /* out of range? */
774  else if (position > this->dimensions->size())
775  {
776  /* no size in this dimension */
777  return IntegerZero;
778  }
779  else /* return the specific dimension */
780  {
781  return this->dimensions->get(position);
782  }
783  }
784 }
785 
787 /******************************************************************************/
788 /* Function: create a supplier for this array */
789 /******************************************************************************/
790 {
791  size_t maxCount = this->size();
792  if (maxItems != OREF_NULL)
793  {
794  maxCount = maxItems->requiredNonNegative(OREF_positional, ARG_ONE);
795  }
796 
797  size_t slotCount = this->size(); /* get the array size */
798  size_t itemCount = this->items(); /* and the actual count in the array */
799  size_t arraySize = min(itemCount, maxCount);
800 
801  RexxArray *values = new_array(arraySize); /* get the values array */
802  RexxArray *indexes = new_array(arraySize); /* and an index array */
803 
804  ProtectedObject v(values);
805  ProtectedObject s(indexes);
806 
807  size_t count = 0; /* next place to add */
808  for (size_t i = 1; i <= slotCount; i++)
809  { /* loop through the array */
810  if (count >= maxCount) break;
811  RexxObject *item = this->get(i); /* get the next item */
812  if (item != OREF_NULL)
813  { /* got an item here */
814  count++;
815  values->put(item, count); /* copy over to the values array */
816 
817  /* add the index location */
818  indexes->put((RexxObject*)convertIndex(i), count);
819  }
820  }
821 
822  return new_supplier(values, indexes);
823 }
824 
825 
827 /******************************************************************************/
828 /* Function: Set a new expansion array item */
829 /******************************************************************************/
830 {
831  OrefSet(this, this->expansionArray, (RexxArray *)expansion);
832 }
833 
835 /******************************************************************************/
836 /* Function: Determine if a position element is "out-of-bounds" */
837 /******************************************************************************/
838 {
839  return (RexxInteger *) ((position < this->size()) ? TheTrueObject : TheFalseObject);
840 }
841 
842 
843 bool RexxArray::validateIndex( /* validate an array index */
844  RexxObject **_index, /* array index (possibly multi-dim) */
845  size_t indexCount, /* size of the index array */
846  size_t _start, /* starting point on the array */
847  size_t bounds_error, /* raise errors on out-of-bounds */
848  stringsize_t &position) // returned position
849 /******************************************************************************/
850 /* Function: Process and validate a potentially multi-dimensional array */
851 /* index. If the index is out of bounds in any dimension it will */
852 /* either return false or raise an error, depending on the bounds */
853 /* checking parameter. */
854 /******************************************************************************/
855 {
856  RexxObject *value; /* individual index value */
857  size_t numsubs; /* number of subscripts */
858  size_t i; /* loop counter */
859  size_t multiplier; /* accumlation factor */
860  size_t offset; /* accumulated offset */
861  size_t _dimension; /* current working dimension */
862  size_t numSize; /* temporary long variable */
863 
864 
865  // do we really have a single index item given as an array?
866  if (indexCount == 1 && _index[0] != OREF_NULL && isOfClass(Array, _index[0]))
867  {
868  // we process this exactly the same way, but swap the count and
869  // pointers around to be the array data.
870  RexxArray *indirect = (RexxArray *)_index[0];
871  indexCount = indirect->items();
872  _index = indirect->data();
873  }
874 
875  /* Is this array one-dimensional? */
876  if (isSingleDimensional())
877  {
878  /* Too many subscripts? Say so. */
879  if (indexCount > 1)
880  {
881  /* should the array be extended? */
882  if ((bounds_error & ExtendUpper) && this->dimensions == OREF_NULL)
883  {
884  /* anytyhing in the array? */
885  /* or explicitly created array with 0*/
886  /* elements (.array~new(0)) */
887  if (this->size() != 0)
888  {
889  /* Yes, number of dims can't change */
890  /* report apropriate bounds */
892  }
893  else
894  {
895  /* its empty, entendarray for new siz*/
896  /* extend the array. */
897  this->extendMulti(_index, indexCount, _start);
898  /* Call us again to get position, now*/
899  /* That the array is extended. */
900  return this->validateIndex(_index, indexCount, _start, bounds_error, position);
901  }
902  }
903 
904  else if (bounds_error & RaiseBoundsTooMany)
905  {
906  /* anytyhing in the array? */
907  /* or explicitly created array with 0*/
908  /* elements (.array~new(0)) */
909  if (this->dimensions != OREF_NULL || this->size() != 0)
910  {
911  /* report apropriate bounds */
913  }
914  else
915  {
916  return false; /* just report not here */
917  }
918  }
919  else
920  {
921  return false; /* not fixed yet, but don't complain */
922  }
923  }
924  /* Too few? subscripts? Say so. */
925  else if (indexCount == 0)
926  {
927  /* report apropriate bounds */
928  reportException(Error_Incorrect_method_minarg, OREF_positional, _start);
929  }
930  /* validate integer index */
931  position = _index[0]->requiredPositive(OREF_positional, (int)_start);
932  /* out of bounds? */
933  if (position > this->size() )
934  {
935  if (position >= MAX_FIXEDARRAY_SIZE)
936  {
938  }
939  /* are we to expand the array? */
940  if (bounds_error & ExtendUpper)
941  {
942  /* yes, compute amount to expand */
943  this->extend(position - this->size());
944 
945  }
946  /* need to raise an error? */
947  else if (bounds_error & RaiseBoundsUpper)
948  {
950  }
951  else
952  {
953  return false; /* just return indicator */
954  }
955  }
956  }
957  else
958  { /* multidimensional array */
959  /* get the number of subscripts */
960  numsubs = indexCount;
961  numSize = this->dimensions->size();/* Get the size of dimension */
962  /* right number of subscripts? */
963  if (numsubs == numSize)
964  {
965  multiplier = 1; /* multiply by 1 for first dimension */
966  offset = 0; /* no accumulated offset */
967 
968  for (i = numsubs; i > 0; i--)
969  { /* loop through the dimensions */
970 
971  value = _index[i - 1];
972 
973  if (value == OREF_NULL) /* not given? */
974  {
975  /* this is an error too */
976  reportException(Error_Incorrect_method_noarg, OREF_positional, i + _start);
977  }
978  /* validate integer index */
979  position = value->requiredPositive(OREF_positional, (int)i);
980  /* get the current dimension */
981  _dimension = ((RexxInteger *)this->dimensions->get(i))->getValue();
982  if (position > _dimension)
983  { /* too large? */
984  /* should the array be extended? */
985  if (bounds_error & ExtendUpper)
986  {
987  /* go extend it. */
988  this->extendMulti(_index, indexCount, _start);
989  /* Call us again to get position, now*/
990  /* That the array is extended. */
991  return this->validateIndex(_index, indexCount, _start, bounds_error, position);
992  }
993  /* need to raise an error? */
994  else if (bounds_error & RaiseBoundsUpper)
995  {
997  }
998  else
999  {
1000  return false; /* just return indicator */
1001  }
1002  }
1003  /* calculate next offset */
1004  offset += multiplier * (position - 1);
1005  multiplier *= _dimension; /* step the multiplier */
1006  }
1007  position = offset + 1; /* get accumulated position */
1008  }
1009  /* Not enough subscripts? */
1010  else if (numsubs < numSize)
1011  {
1013  }
1014  else /* Must be too many subscripts */
1015  /* should the array be extended? */
1016 #ifdef EXTEND_DIMENSIONS
1017  if (bounds_error & ExtendUpper)
1018  {
1019  /* anytyhing in the array? */
1020  if (this->size() != 0)
1021  {
1022  /* Yes, number of dims can't change */
1023  /* report apropriate bounds */
1024  reportException(Error_Incorrect_method_maxarg, OREF_positional, numSize);
1025  }
1026  else
1027  {
1028  /* array empty, extend the array */
1029  this->extendMuti(_index, indexCount, _start);
1030  /* Call us again to get position, now*/
1031  /* That the array is extended. */
1032  return this->validateIndex(_index, indexCount, _start, bounds_error, position);
1033  }
1034  }
1035  else
1036  {
1038  }
1039 #else
1041 #endif
1042  }
1043  return true; /* return the position */
1044 }
1045 
1046 
1047 /**
1048  * Make sure that the array has been expanded to sufficient
1049  * size for a primitive put operation.
1050  *
1051  * @param newSize The new required size.
1052  */
1053 void RexxArray::ensureSpace(size_t newSize)
1054 {
1055  /* out of bounds? */
1056  if (newSize > this->size())
1057  {
1058  if (newSize >= MAX_FIXEDARRAY_SIZE)
1059  {
1061  }
1062  /* yes, compute amount to expand */
1063  this->extend(newSize - this->size());
1064 
1065  }
1066 }
1067 
1068 
1069 
1071 /******************************************************************************/
1072 /* Function: Return the array size as an integer object */
1073 /******************************************************************************/
1074 {
1075  return new_integer(this->size());
1076 }
1077 
1078 /**
1079  * Section an array to the given size.
1080  *
1081  * @param _start The starting point of the section.
1082  * @param _end The end section index
1083  *
1084  * @return A new array representing the given section.
1085  */
1086 RexxArray * RexxArray::section(size_t _start, size_t _end)
1087 {
1088  size_t newSize; /* Size for new array. */
1089  RexxArray *newArray; /* The new array. */
1090 
1091  if (_start == 0) /* starting position specified? */
1092  {
1093  _start = 1; /* nope, start at begining */
1094  }
1095 
1096  /* ending position omitted */
1097  /* or, End pos past end of array? */
1098  if (_end == 0 || _end > this->size())
1099  {
1100  _end = this->size(); /* yes, use end of array */
1101  }
1102  if (_start <= _end)
1103  { /* is start before end? */
1104  newSize = _end + 1 - _start; /* yes, compute new size */
1105  /* Get new array, of needed size */
1106  newArray = (RexxArray *)new_array(newSize);
1107  // a new array cannot be oldspace, by definition. It's safe to use
1108  // memcpy to copy the data.
1109  /* yes, we can do a memcpy */
1110  memcpy(newArray->data(), slotAddress(_start), sizeof(RexxObject *) * newSize);
1111  }
1112  else
1113  {
1114  /* return 0 element array */
1115  newArray = (RexxArray *)new_array((size_t)0);
1116  }
1117  return newArray; /* return the newly created array */
1118 }
1119 
1120 /**
1121  * Extract a section of the array as another array
1122  *
1123  * @param _start The starting index position
1124  * @param _end The number of items to section.
1125  *
1126  * @return A new array containing the section elements.
1127  */
1129 {
1130  /* multidimensional array? */
1131  if (isMultiDimensional())
1132  {
1133  /* this is an error */
1135  }
1136 
1137  // the index is required
1138  requiredArgument(_start, OREF_positional, ARG_ONE);
1139  size_t nstart; // array position
1140 
1141  // validate the index and expand if necessary.
1142  this->validateIndex(&_start, 1, 1, RaiseBoundsInvalid | RaiseBoundsTooMany, nstart);
1143  size_t nend = 0; ;
1144  if (_end == OREF_NULL) /* If no end position specified, */
1145  {
1146  nend = this->size(); /* Defaults to last element */
1147  }
1148  else
1149  { /* End specified - check it out */
1150  nend = _end->requiredNonNegative(OREF_positional, ARG_TWO);
1151  }
1152 
1153  if (!isOfClass(Array, this)) /* actually an array subclass? */
1154  {
1155  /* need to do this the slow way */
1156  return this->sectionSubclass(nstart, nend);
1157  }
1158 
1159  if (nstart > this->size()) /* too big? */
1160  {
1161  // return a zero-size array
1162  return (RexxArray *)(((RexxArray *)TheNullArray)->copy());
1163  }
1164  else
1165  {
1166  /* go past the bounds? */
1167  if (nend > this->size() - nstart + 1)
1168  {
1169  nend = this->size() - nstart + 1;/* truncate to the end */
1170  }
1171  if (nend == 0) /* requesting zero? */
1172  {
1173  /* return zero elements */
1174  return (RexxArray *)(((RexxArray *)TheNullArray)->copy());
1175  }
1176  else
1177  { /* real sectioning to do */
1178  /* create a new array */
1179  RexxArray *rref = (RexxArray *)new_array(nend);
1180  for (size_t i = 1; i <= nend; i++)
1181  { /* loop through the elements */
1182  /* copy an element */
1183  rref->put(this->get(nstart + i - 1), i);
1184  }
1185  return rref; /* return the new array */
1186  }
1187  }
1188 }
1189 
1191  size_t _start, /* starting element */
1192  size_t _end ) /* ending element */
1193 /******************************************************************************/
1194 /* Function: Rexx level section method */
1195 /******************************************************************************/
1196 {
1197  size_t i; /* loop counter */
1198  RexxArray *newArray; /* returned array */
1199  ProtectedObject result;
1200 
1201  if (_start > this->size()) /* too big? */
1202  {
1203  this->behaviour->getOwningClass()->sendMessage(OREF_NEW, IntegerZero, result);
1204  newArray = (RexxArray *)(RexxObject *)result;
1205  }
1206  /* return a zero element one */
1207  else
1208  {
1209  if (_end > this->size() - _start + 1)
1210  {
1211  /* go past the bounds? */
1212  _end = this->size() - _start + 1;/* truncate to the end */
1213  }
1214  if (_end == 0) /* requesting zero? */
1215  {
1216  this->behaviour->getOwningClass()->sendMessage(OREF_NEW, IntegerZero, result);
1217  newArray = (RexxArray *)(RexxObject *)result;
1218  }
1219  /* return a zero element one */
1220  else
1221  { /* real sectioning to do */
1222  /* create a new array */
1223  this->behaviour->getOwningClass()->sendMessage(OREF_NEW, new_integer(_end), result);
1224  newArray = (RexxArray *)(RexxObject *)result;
1225  for (i = 1; i <= _end; i++) /* loop through the elements */
1226  {
1227  /* copy an element */
1228  newArray->sendMessage(OREF_PUT, this->get(_start + i - 1), new_integer(i));
1229  }
1230  }
1231  }
1232  return newArray; /* return the new array */
1233 }
1234 
1236 /******************************************************************************/
1237 /* Function: Retrieve the first element index from the array as an integer */
1238 /* object */
1239 /******************************************************************************/
1240 {
1241  /* get the address of the first */
1242  /*element in the array */
1243  RexxObject **thisObject = this->expansionArray->objects;
1244  size_t _arraySize = this->size(); /* get the size of the array */
1245  /* find first position in the */
1246  /*array with data */
1247 
1248  size_t i;
1249  for (i = 0; i < _arraySize && thisObject[i] == OREF_NULL; i++);
1250 
1251  if (i == _arraySize) /* is array empty */
1252  {
1253  return TheNilObject; /* return nil object */
1254  }
1255  else
1256  {
1257  /* return index of the first entry */
1258  return convertIndex(i + 1);
1259  }
1260 }
1261 
1263 /******************************************************************************/
1264 /* Function: Return the index of the last array item as an integer object */
1265 /******************************************************************************/
1266 {
1267  // for an empy array, the index is .nil
1268  if (lastElement == 0)
1269  {
1270  return TheNilObject;
1271  }
1272 
1273  // return as an object
1274  return (RexxObject *)convertIndex(lastElement);
1275 }
1276 
1277 /**
1278  * Return the first item in the array, or .nil if the
1279  * array is empty.
1280  *
1281  * @return The first item in the array
1282  */
1284 {
1285  /* get the address of the first */
1286  /*element in the array */
1287  RexxObject **thisObject = this->expansionArray->objects;
1288  size_t _arraySize = this->size(); /* get the size of the array */
1289  /* find first position in the */
1290  /*array with data */
1291 
1292  for (size_t i = 0; i < _arraySize; i++)
1293  {
1294  // if we have a non-nil object, return it
1295  if (thisObject[i] != OREF_NULL)
1296  {
1297  return thisObject[i];
1298  }
1299  }
1300  // not found, return .nil
1301  return TheNilObject;
1302 }
1303 
1304 /**
1305  * Return the last item in the array.
1306  *
1307  * @return The last item, or .nil if the array is empty.
1308  */
1310 {
1311  // for an empy array, the item is .nil
1312  if (lastElement == 0)
1313  {
1314  return TheNilObject;
1315  }
1316 
1317  // return the last item
1318  return (RexxObject *)get(lastElement);
1319 }
1320 
1322 /******************************************************************************/
1323 /* Function: Return the index of the last array item as an integer object */
1324 /******************************************************************************/
1325 {
1326  return lastElement; // we've kept track of this
1327 }
1328 
1329 RexxObject *RexxArray::nextRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
1330 /******************************************************************************/
1331 /* Function: Return the next entry after a given array index */
1332 /******************************************************************************/
1333 {
1334  size_t position;
1335  /* go validate the index */
1336  if (!this->validateIndex(arguments, argCount, 1, RaiseBoundsTooMany | RaiseBoundsInvalid, position))
1337  {
1338  // out of bounds results in the .nil object
1339  return TheNilObject;
1340  }
1341  /* get the address of the first */
1342  /*element in the array */
1343  RexxObject **thisObject = this->data();
1344  size_t _arraySize = this->size(); /* get the size of the array */
1345  /* find next entry in the array with */
1346  /*data */
1347 
1348  size_t i;
1349  for (i = position; i < _arraySize && thisObject[i] == OREF_NULL; i++);
1350 
1351  if (i >= this->size())
1352  {
1353  return TheNilObject; /* return nil object */
1354  }
1355  else
1356  {
1357  /* return index of the next entry */
1358  return convertIndex(i + 1);
1359  }
1360 }
1361 
1362 RexxObject *RexxArray::previousRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
1363 /******************************************************************************/
1364 /* Function: Return the index preceeding a given index */
1365 /******************************************************************************/
1366 {
1367  size_t position;
1368 
1369  this->validateIndex(arguments, argCount, 1, RaiseBoundsTooMany | RaiseBoundsInvalid, position);
1370  /* get the index object into an */
1371  /*integer object */
1372  size_t i = position;
1373 
1374  size_t _arraySize = this->size(); /* get the size of the array */
1375 
1376  if (i > _arraySize) /* beyond the size of the array? */
1377  {
1378  /* set i to one more than the last */
1379  /*entry */
1380  i = _arraySize;
1381  }
1382  else
1383  {
1384  i = i-1; /* Account for 0 based 'C' arrays */
1385  }
1386 
1387  /* get the address of the first */
1388  /*element in the array */
1389  RexxObject **thisObject = this->expansionArray->objects;
1390  /* find previous entry in the */
1391  /*array with data */
1392  for (; i > 0 && thisObject[i-1] == OREF_NULL; i--);
1393 
1394  if (i == 0)
1395  {
1396  return TheNilObject; /* return nil object */
1397  }
1398  else
1399  {
1400  /* return the index to the */
1401  /*previous entry */
1402  return convertIndex(i);
1403  }
1404 }
1405 
1406 RexxObject *RexxArray::hasIndexRexx(RexxObject ** _index, size_t _indexCount, size_t _named_argCount)
1407 /******************************************************************************/
1408 /* Function: True if array has an entry for the index, false otherwise */
1409 /* Note: This routine should not raise an error, regardless of the indices */
1410 /* being used. The only error produced is if no parms were passed. */
1411 /******************************************************************************/
1412 {
1413  stringsize_t position; /* array position */
1414 
1415  /* go validate the index */
1416  if (!this->validateIndex(_index, _indexCount, 1, RaiseBoundsTooMany | RaiseBoundsInvalid, position))
1417  {
1418  /* this is false */
1419  return TheFalseObject;
1420 
1421  }
1422  else /* check the position */
1423  {
1424  /* have a real entry? */
1425  if (*(this->data() + position - 1) != OREF_NULL)
1426  {
1427  /* got a true */
1428  return TheTrueObject;
1429  }
1430  else
1431  {
1432  /* no index here */
1433  return TheFalseObject;
1434  }
1435  }
1436 }
1437 
1438 bool RexxArray::hasIndexNative(size_t _index)
1439 /******************************************************************************/
1440 /* Function: Determine if an element exist for a position */
1441 /******************************************************************************/
1442 {
1443  /* in bounds and here? */
1444  if (_index > 0 && _index <= this->size() && *(this->data() + _index - 1) != OREF_NULL)
1445  {
1446  return true; /* this is true */
1447  }
1448  else
1449  {
1450  return false; /* nope, don't have it */
1451  }
1452 }
1453 
1455 /******************************************************************************/
1456 /* Function: Return a single dimension array of self, with only items that */
1457 /* has values, so it will be of size items. */
1458 /******************************************************************************/
1459 {
1460  // for an array, this is the all items value.
1461  return this->allItems();
1462 }
1463 
1464 
1465 /**
1466  * Return an array of all real items contained in the collection.
1467  *
1468  * @return An array with all of the array items (non-sparse).
1469  */
1471 {
1472  size_t maxCount = this->size();
1473  if (maxItems != OREF_NULL)
1474  {
1475  maxCount = maxItems->requiredNonNegative(OREF_positional, ARG_ONE);
1476  }
1477 
1478  // get a result array of the appropriate size
1479  size_t arraySize = min(this->items(), maxCount);
1480  RexxArray *newArray = (RexxArray *)new_array(arraySize);
1481 
1482  // we need to fill in based on actual items, not the index.
1483  size_t count = 0;
1484  RexxObject **item = this->data();
1485  // loop through the array, copying all of the items.
1486  for (size_t iterator = 0; iterator < this->size(); iterator++ )
1487  {
1488  if (count >= maxCount) break;
1489  // if this is a real array item, copy over to the result
1490  if (item[iterator] != OREF_NULL)
1491  {
1492  newArray->put(item[iterator], ++count);
1493  }
1494  }
1495  return newArray;
1496 }
1497 
1498 
1499 /**
1500  * Return an array of all indices of real array items contained
1501  * in the collection.
1502  *
1503  * @return An array with all of the array indices (non-sparse).
1504  */
1506 {
1507  size_t maxCount = this->size();
1508  if (maxIndexes != OREF_NULL)
1509  {
1510  maxCount = maxIndexes->requiredNonNegative(OREF_positional, ARG_ONE);
1511  }
1512 
1513  // get a result array of the appropriate size
1514  size_t arraySize = min(this->items(), maxCount);
1515  RexxArray *newArray = (RexxArray *)new_array(arraySize);
1516  ProtectedObject p(newArray);
1517 
1518  // we need to fill in based on actual items, not the index.
1519  size_t count = 0;
1520  RexxObject **item = this->data();
1521  // loop through the array, copying all of the items.
1522  for (size_t iterator = 0; iterator < this->size(); iterator++ )
1523  {
1524  if (count >= maxCount) break;
1525  // if this is a real array item, add an integer index item to the
1526  // result collection.
1527  if (item[iterator] != OREF_NULL)
1528  {
1529  newArray->put(convertIndex(iterator+1), ++count);
1530  }
1531  }
1532  return newArray;
1533 }
1534 
1535 // Temporary bypass for BUG #1700606
1536 #if 0
1538 /******************************************************************************/
1539 /* Function: Handle a REQUEST('STRING') request for a REXX string object */
1540 /******************************************************************************/
1541 {
1542  return this->makeString((RexxString *)OREF_NULL); /* forward to the real makestring method */
1543 }
1544 #endif
1545 
1547 {
1548  return toString(format, separator);
1549 }
1550 
1551 RexxString *RexxArray::toString( /* concatenate array elements to create string object */
1552  RexxString *format, /* format of concatenation (one of: "C", "L") */
1553  RexxString *separator) /* separator to use if "L" is specified for format */
1554 /******************************************************************************/
1555 /* Function: Make a string out of an array */
1556 /******************************************************************************/
1557 {
1558  size_t _items;
1559  size_t i;
1560  RexxArray *newArray; /* New array */
1561  RexxString *newString;
1562  RexxString *line_end_string; /* converted substitution value */
1563  RexxMutableBuffer *mutbuffer;
1564  RexxObject *item; /* inserted value item */
1565  int i_form = 0; /* 1 == line, 2 == char */
1566 
1567  mutbuffer = ((RexxMutableBufferClass*) TheMutableBufferClass)->newRexx(NULL, 0, 0);
1568  ProtectedObject p1(mutbuffer);
1569 
1570  newArray = this->makeArray(); /* maybe multidimensional, make onedimensional */
1571  ProtectedObject p2(newArray);
1572 
1573  _items = newArray->items(); /* and the actual count in the array */
1574 
1575  if (format != OREF_NULL)
1576  {
1577  // a string value is required here
1578  format = stringArgument(format, OREF_positional, ARG_ONE);
1579  }
1580 
1581  if (format == OREF_NULL)
1582  {
1583  i_form = 2; /* treat item as LINE by default */
1584  }
1585  else if (toupper((format->getStringData()[0])) == 'C')
1586  {
1587  i_form = 1;
1588  }
1589  else if (toupper((format->getStringData()[0])) == 'L')
1590  {
1591  i_form = 2;
1592  }
1593  else
1594  {
1596  }
1597 
1598  if (i_form == 1) /* character oriented processing */
1599  {
1600  if (separator != OREF_NULL)
1601  {
1603 
1604  }
1605 
1606  for (i = 1; i <=_items ; i++) /* loop through the array */
1607  {
1608  item = newArray->get(i); /* get the next item */
1609  if (item != OREF_NULL)
1610  {
1611  RexxObject * _stringValue = item->requiredString();
1612  if (_stringValue != TheNilObject)
1613  {
1614  ProtectedObject p(_stringValue);
1615  mutbuffer->append(_stringValue);
1616  }
1617  }
1618  }
1619  }
1620  else if (i_form == 2) /* line oriented processing */
1621  {
1622  if (separator != OREF_NULL)
1623  {
1624  line_end_string = stringArgument(separator, OREF_positional, ARG_TWO);
1625  }
1626  else
1627  {
1628  line_end_string = new_string(line_end);
1629  }
1630 
1631  ProtectedObject p3(line_end_string);
1632  bool first = true;
1633 
1634  for (i = 1; i <= _items; i++) /* loop through the array */
1635  {
1636  item = newArray->get(i); /* get the next item */
1637  if (item != OREF_NULL)
1638  {
1639  // append a linend between the previous item and this one.
1640  if (!first)
1641  {
1642  mutbuffer->append((RexxObject *) line_end_string);
1643  }
1644  RexxObject *_stringValue = item->requiredString();
1645  if (_stringValue != TheNilObject)
1646  {
1647  ProtectedObject p(_stringValue);
1648  mutbuffer->append(_stringValue);
1649  }
1650  first = false;
1651  }
1652  }
1653  }
1654 
1655  newString = mutbuffer->makeString();
1656  return newString;
1657 }
1658 
1659 RexxObject *RexxArray::join( /* join two arrays into one */
1660  RexxArray *other) /* array to be appended to self */
1661 /******************************************************************************/
1662 /* Function: Join two arrays into one array */
1663 /******************************************************************************/
1664 {
1665  /* get new array, total size is size */
1666  /* of both arrays. */
1667  RexxArray *newArray = (RexxArray*)new_array(this->size() + other->size());
1668  // it's safe to just copy the references because the newArray will be new space
1669  /* copy first array into new one */
1670  memcpy(newArray->data(), this->data(), this->dataSize());
1671  /* copy 2nd array into the new one */
1672  /* after the first one. */
1673  memcpy((void *)newArray->slotAddress(this->size() + 1), other->data(), other->dataSize());
1674  return newArray; /* All done, return joined array */
1675 
1676 }
1677 
1678 void RexxArray::resize(void) /* resize this array to be a NULLARRA*/
1679 /******************************************************************************/
1680 /* Function: An Array is being expanded so chop off the data (array) */
1681 /* portion of this array. */
1682 /******************************************************************************/
1683 {
1684  size_t i;
1685  /* Has the array already been */
1686  /* expanded ? */
1687  if (this->expansionArray == this)
1688  {
1689  /* no, then we resize the array */
1690  /* is this array in OldSpace ? */
1691  if (this->isOldSpace())
1692  {
1693  /* Old Space, remove any reference */
1694  /* to new space from memory tables */
1695  for (i = 0; i < this->arraySize; i++)
1696  {
1697  OrefSet(this, this->objects[i], OREF_NULL);
1698  }
1699  }
1700  /* resize the array object */
1701  memoryObject.reSize(this, sizeof(RexxArray));
1702  this->arraySize = 0; /* outer array has no elements */
1703  }
1704 }
1705 
1707  size_t amount) /* amount to shrink an array */
1708 /******************************************************************************/
1709 /* Function: Shrink an array without reallocating any elements */
1710 /* Single Dimension ONLY */
1711 /******************************************************************************/
1712 {
1713  size_t _size = this->size(); /* get the size */
1714  size_t newSize = _size - amount; /* get the new size */
1715 
1716  this->expansionArray->arraySize = newSize;
1717 }
1718 
1720  RexxObject *target) /* target object to locate */
1721 /*****************************************************************************/
1722 /* Function: To search a list in the form of an array for an item, returning*/
1723 /* the index */
1724 /*****************************************************************************/
1725 {
1726  size_t _size = this->size(); /* get the array size */
1727  for (size_t i = 1; i <= _size; i++)
1728  { /* spin through the array */
1729  if (this->get(i) == target) /* is this the one? */
1730  {
1731  return i; /* return the index */
1732  }
1733  }
1734  return 0; /* not found here */
1735 }
1736 
1737 
1738 RexxArray *RexxArray::extend( /* join two arrays into one */
1739  size_t extension) /* number of elements to extend */
1740 /******************************************************************************/
1741 /* Function: Extend an array by a given number of elements */
1742 /* Single Dimension ONLY */
1743 /******************************************************************************/
1744 {
1745  /* do we really need to extend array */
1746  /* or just adjust size. */
1747  if (this->size() + extension <= this->maximumSize)
1748  {
1749  /* adjust the size . */
1750  this->expansionArray->arraySize += extension;
1751  return this;
1752  }
1753 
1754  size_t newSize = this->size() + extension;
1755  size_t extendSize = this->size() / 2;
1756 
1757  /* get a new array, total size is */
1758  /* size of both arrays. */
1759  RexxArray *newArray = (RexxArray *)new_array(newSize + extendSize);
1760  /* If none of the objects are in */
1761  /* OldSpace, we can skip the */
1762  /* OrefSets and just copy */
1763  /* copy ourselves into the new array */
1764  memcpy(newArray->data(), this->data(), this->dataSize());
1765  this->resize(); /* adjust ourself to be null arrayobj*/
1766 
1767  newArray->setExpansion(OREF_NULL); /* clear the new expansion array */
1768  /* set new expansion array */
1769  OrefSet(this, this->expansionArray, newArray);
1770  /* keep max Size value in synch */
1771  /* with expansion. */
1772  this->maximumSize = newArray->maximumSize;
1773  /* make sure size is correct. */
1774  newArray->arraySize = newSize;
1775  return this; /* All done, return array */
1776 }
1777 
1778 
1779 /**
1780  * Find the index of a single item in the array.
1781  *
1782  * @param item The item to locate.
1783  *
1784  * @return The numeric index of the item.
1785  */
1787 {
1788  for (size_t i = 1; i <= this->size(); i++)
1789  {
1790  RexxObject *test = get(i);
1791 
1792  // if there's an object in the slot, compare it.
1793  if (test != OREF_NULL)
1794  {
1795  // if the items are equal, return the index
1796  if (item->equalValue(test))
1797  {
1798  return i;
1799  }
1800  }
1801  }
1802  return 0;
1803 }
1804 
1805 
1806 /**
1807  * Convert an internal index item into "external" form. Handles
1808  * both single- and multi-dimensional arrays.
1809  *
1810  * @param idx The internal index to convert.
1811  *
1812  * @return An index object proper for the array type.
1813  */
1815 {
1816  // single dimension array? This is easy
1817  if (isSingleDimensional())
1818  {
1819  return new_integer(idx);
1820  }
1821  else
1822  {
1823  // compose a composite index
1824  return indexToArray(idx);
1825  }
1826 }
1827 
1828 
1829 /**
1830  * Convert a multi-dimensional array index into an array
1831  * of index values for the flattened dimension.
1832  *
1833  * @param idx The index to covert.
1834  *
1835  * @return An array of the individual index items.
1836  */
1838 {
1839  // work with an origin-origin zero version of the index, which is easier
1840  // do work with.
1841  idx--;
1842  // get the number of dimensions specified.
1843  size_t dims = this->dimensions->size();
1844  // get an array we fill in as we go
1845  RexxArray * _index = new_array(dims);
1846 
1847  ProtectedObject p(_index);
1848 
1849  for (size_t i = dims; i > 0; i--)
1850  {
1851  // get the next dimension size
1852  size_t _dimension = ((RexxInteger *)this->dimensions->get(i))->getValue();
1853  // now get the remainder. This tells us the position within this
1854  // dimension of the array. Make an integer object and store in the
1855  // array.
1856  size_t digit = idx % _dimension;
1857  // the digit is origin-zero, but the Rexx index is origin-one.
1858  _index->put(new_integer(digit + 1), i);
1859  // now strip out that portion of the index.
1860  idx = (idx - digit) / _dimension;
1861  }
1862  return _index;
1863 }
1864 
1865 
1866 /**
1867  * Return the index for the first occurrence of the target in
1868  * the array.
1869  *
1870  * @param target The target object.
1871  *
1872  * @return The index for the array. For a multi-dimensional array, this
1873  * returns an array of indices.
1874  */
1876 {
1877  // we require the index to be there.
1878  requiredArgument(target, OREF_positional, ARG_ONE);
1879  // see if we have this item. If not, then
1880  // we return .nil.
1881  size_t _index = findSingleIndexItem(target);
1882 
1883  if (_index == 0)
1884  {
1885  return TheNilObject;
1886  }
1887 
1888  return convertIndex(_index);
1889 }
1890 
1891 
1892 /**
1893  * Remove the target object from the collection.
1894  *
1895  * @param target The target object.
1896  *
1897  * @return The removed object (same as target).
1898  */
1900 {
1901  // we require the index to be there.
1902  requiredArgument(target, OREF_positional, ARG_ONE);
1903  // see if we have this item. If not, then
1904  // we return .nil.
1905  size_t _index = findSingleIndexItem(target);
1906 
1907  if (_index == 0)
1908  {
1909  return TheNilObject;
1910  }
1911  // remove the item at the location
1912  remove(_index);
1913  return target;
1914 }
1915 
1916 
1917 /**
1918  * Test if an item is within the array.
1919  *
1920  * @param target The target test item.
1921  *
1922  * @return .true if this item exists in the array. .false if it does not
1923  * exist.
1924  */
1926 {
1927  // this is pretty simple. One argument, required, and just search to see
1928  // if we have it.
1929  requiredArgument(target, OREF_positional, ARG_ONE);
1930  return findSingleIndexItem(target) == 0 ? TheFalseObject : TheTrueObject;
1931 }
1932 
1933 
1934 
1936  COPYELEMENTPARM *parm,
1937  size_t newDimension)
1938 /******************************************************************************/
1939 /* Function: Recursive routine to copy element from one multiDim array */
1940 /* to another. */
1941 /******************************************************************************/
1942 {
1943  size_t skipAmount; /* amount to skip for increased */
1944  /* dimension. */
1945  size_t newDimSize;
1946  size_t oldDimSize;
1947  size_t oldDimension;
1948  size_t i; /* count for each subscript at */
1949  /* this dimension */
1950 
1951  /* At the point where we can */
1952  /* copy elements? */
1953  /* ending condition for recusion */
1954  if (newDimension == parm->firstChangedDimension)
1955  {
1956  /* is new array in OldSpace? */
1957  if (parm->newArray->isOldSpace())
1958  {
1959  /* Yes,need to do OrefSets */
1960  /* For each element to copy */
1961  for (i = 1; i <= parm->copyElements; i++, parm->startNew++, parm->startOld++ )
1962  {
1963  /* set the newvalue. */
1964  OrefSet(parm->newArray, *parm->startNew, *parm->startOld);
1965  }
1966  }
1967  else
1968  {
1969  /* not old Spcae we can do memcpy */
1970  memcpy(parm->startNew, parm->startOld, sizeof(RexxObject *) * parm->copyElements);
1971  /* update pointers */
1972  parm->startNew += parm->copyElements;
1973  parm->startOld += parm->copyElements;
1974  }
1975  /* now bump past space for */
1976  /* additional size of dimension */
1977  parm->startNew += parm->skipElements;
1978  }
1979  else
1980  {
1981  /* Compute the old dimension num */
1982  oldDimension = newDimension - parm->deltaDimSize;
1983  /* Get size for new Dimension */
1984  newDimSize = ((RexxInteger *)parm->newDimArray->get(newDimension))->getValue();
1985  /* Get size for old Dimension */
1986  oldDimSize = ((RexxInteger *)parm->oldDimArray->get(oldDimension))->getValue();
1987  /* For each subscript at this */
1988  for (i= 1; i <= oldDimSize; i++)
1989  {/* dimension, (of old size) */
1990  /* copy elelments. */
1991  copyElements(parm, newDimension + 1);
1992  }
1993  if (newDimSize > oldDimSize)
1994  { /* Was this dimension expanded? */
1995  /* compute total space need for */
1996  /* block of all lower dimensions */
1997  for (i = parm->newDimArray->size(), skipAmount = 1;
1998  i > newDimension;
1999  skipAmount *= ((RexxInteger *)parm->newDimArray->get(i))->getValue(), i--);
2000  /* multiple by delta add at this */
2001  /* dimension. */
2002  skipAmount *= (newDimSize - oldDimSize);
2003  /* Bump our start pointer past */
2004  /* empty space added for this */
2005  /* dimension. */
2006  parm->startNew += skipAmount;
2007  }
2008  }
2009  /* all done at this level return */
2010  /* to caller. */
2011  return;
2012 }
2013 
2014 
2015 RexxArray *RexxArray::extendMulti( /* Extend multi array */
2016  RexxObject ** _index, /* Dimension array is to be */
2017  size_t _indexCount, /* number of indices in the index */
2018  size_t _start) /* Starting position of dimensions */
2019  /* in index. */
2020 /******************************************************************************/
2021 /* Function: Extend an array by a given number of elements */
2022 /* Multiple Dimensions */
2023 /* Index either has more dimensions that the current array or */
2024 /* is the same number. So expansion array will have same number */
2025 /* of dimensions as index. */
2026 /* So examine size of each dimension and new array will be max */
2027 /* of two sizes. */
2028 /* */
2029 /* NOTE: Even though we don't currently allow for changing the number */
2030 /* of dimensions in an array, the support to do this, is included */
2031 /* in this method. We currently won't be called for this condition */
2032 /* but if we ever are, this method should not need to be changed. */
2033 /* */
2034 /******************************************************************************/
2035 {
2036  size_t currDimSize; /* Current size of Dimension */
2037  size_t additionalDim; /* Number of additional DImension */
2038  size_t newDimSize; /* New size for this Dimension */
2039  size_t newDimension; /* Current dimension */
2040  size_t oldDimension; /* Current dimension */
2041  size_t i;
2042  RexxArray *newArray;
2043  RexxArray *newDimArray; /* Array containing new dimension */
2044  size_t newDimArraySize; /* Size of Dimension Array */
2045  size_t accumSize;
2046  size_t firstDimChanged = 0; /* First Dimension to grow */
2047  COPYELEMENTPARM copyParm; /* Structure for copyElement */
2048  size_t tempSize;
2049 
2050  /* New dimension array size of */
2051  /* index array. */
2052  /* index is actually 1 bigger tha */
2053  /* dimension size, since it */
2054  /* contains the new value at 1st */
2055  /* position */
2056 
2057  /* Compute new Size for DimArray */
2058  newDimArraySize = _indexCount;
2059  newDimArray = new_array(newDimArraySize);
2060  ProtectedObject p(newDimArray);
2061  /* extending from single Dimensio */
2062  /* to a multi Dimensionsal array */
2063  if (this->dimensions == OREF_NULL)
2064  {
2065  /* Get value for 1st dimension */
2066  /* its the last element */
2067  i = newDimArraySize - 1;
2068  newDimSize = _index[i]->requiredPositive(OREF_positional, (int)i);
2069  /* Yes, is 1st Dimension going to */
2070  /* be bigger than current size? */
2071  if (newDimSize > this->size())
2072  /* Yes, use new size + buffer for */
2073  /* 1st Dimension */
2074  newDimArray->put(new_integer(newDimSize), newDimArraySize);
2075  else
2076  {
2077  /* nope, use same size for Dim */
2078  tempSize = this->size();
2079  newDimArray->put(new_integer(tempSize), newDimArraySize);
2080  }
2081  }
2082  else
2083  {
2084  for (oldDimension = this->dimensions->size(), newDimension = newDimArraySize;
2085  oldDimension > 0 ;
2086  oldDimension--, newDimension--)
2087  {
2088  /* Get current size of this dimension*/
2089  currDimSize = ((RexxInteger *)this->dimensions->get(oldDimension))->getValue();
2090  /* Get indexd size of this dimension*/
2091 
2092  newDimSize = _index[newDimension - 1]->requiredPositive(OREF_positional, (int)newDimension);
2093  /* does this dimension need to be */
2094  /* expanded. */
2095  if (newDimSize > currDimSize)
2096  {
2097  newDimArray->put((RexxObject *)new_integer(newDimSize), newDimension);
2098  /* has a dimension already been chang*/
2099  if (!firstDimChanged)
2100  {
2101  /* remember the first dimenion chenge*/
2102  firstDimChanged = newDimension;
2103  }
2104  }
2105  else
2106  {
2107  newDimArray->put(this->dimensions->get(oldDimension), newDimension);
2108  }
2109  }
2110  }
2111  /* Was original array single dim */
2112  if (this->dimensions == OREF_NULL)
2113  {
2114  /* additional Dimensions is 1 */
2115  /* minus size, (1st Dimension) */
2116  additionalDim = newDimArraySize - 1;
2117  }
2118  else
2119  {
2120  /* compute number of dimensions added*/
2121  additionalDim = newDimArraySize - this->dimensions->size();
2122  }
2123  /* is index greater than current */
2124  /* dimensions of this array. */
2125  if (additionalDim > 0)
2126  {
2127  /* yes, for remainder of dimensions */
2128  for (newDimension = additionalDim;
2129  newDimension > 0 ;
2130  newDimension--)
2131  {
2132  /* Get indexd size of this dimension*/
2133  newDimSize = ((RexxInteger *)_index[newDimension - 1])->getValue();
2134  /* set up value for this dimension */
2135  newDimArray->put(new_integer(newDimSize), newDimension);
2136  }
2137  }
2138  /* Now create the new array for this */
2139  /* dimension. */
2140  newArray = new (newDimArray->data(), newDimArraySize, TheArrayClass) RexxArray;
2141  ProtectedObject p1(newArray);
2142  /* Anything in original? */
2143  if (this->size())
2144  {
2145  /* Yes, move values into new arra */
2146  /* Extending from single Dimension */
2147  /* or original array was empty */
2148  /* or adding dimensions or increas */
2149  /* last original dimension? */
2150  if (isSingleDimensional() ||
2151  this->size() == 0 ||
2152  !firstDimChanged || firstDimChanged <= additionalDim + 1)
2153  {
2154  /* If none of the objects are in */
2155  /* OldSpace, we can 'cheat' and do */
2156  /* a fast copy (memcpy) */
2157  /* copy ourselves into the new array */
2158  memcpy(newArray->data(), this->data(), sizeof(RexxObject *) * this->size());
2159  }
2160  /* Working with 2 multi-dimensional */
2161  /* Array's. */
2162  else
2163  {
2164  /* Now we need to move all elements */
2165 
2166  /* for all Dimensions before first */
2167  /* to increase. */
2168  for (i = newDimArraySize, accumSize = 1;
2169  i > firstDimChanged ;
2170  accumSize *= ((RexxInteger *)this->dimensions->get(i))->getValue(), i--);
2171  /* Compute lowest largest contig */
2172  /* chunk that can be copied. */
2173  copyParm.copyElements = accumSize * ((RexxInteger *)this->dimensions->get(firstDimChanged))->getValue();
2174  /* Compute amount need to ship */
2175  /* to compete expanded dimension */
2176  copyParm.skipElements = accumSize * (((RexxInteger *)newDimArray->get(firstDimChanged))->getValue() -
2177  ((RexxInteger *)this->dimensions->get(firstDimChanged))->getValue());
2178 
2179  copyParm.startNew = newArray->data();
2180  copyParm.startOld = this->data();
2181  /* Setup parameter structure */
2182  copyParm.firstChangedDimension = firstDimChanged;
2183  copyParm.newArray = newArray;
2184  copyParm.newDimArray = newDimArray;
2185  copyParm.oldDimArray = this->dimensions;
2186  /* Compute delta dimensions size */
2187  copyParm.deltaDimSize = newDimArraySize - this->dimensions->size();
2188  /* do the copy. starting w/ */
2189  /* Highest Dimension */
2190  copyElements(&copyParm, newDimArraySize - this->dimensions->size() + 1);
2191  }
2192  } /* end, if anything in original */
2193 
2194 
2195  this->resize();
2196  /* Set dimensions to be new dimension*/
2197  OrefSet(this, this->dimensions, newDimArray);
2198  newArray->setExpansion(OREF_NULL);
2199  /* update expansion array. */
2200  OrefSet(this, this->expansionArray, newArray);
2201  /* keep max Size value in synch */
2202  /* with expansion. */
2203  this->maximumSize = newArray->maximumSize;
2204  return this; /* All done, return array */
2205 }
2206 
2207 
2208 /**
2209  * Insert an element into the array, shifting all of the
2210  * existing elements at the inserted position and adjusting
2211  * the size accordingly.
2212  *
2213  * @param value The value to insert (can be OREF_NULL to just open a new slot)
2214  * @param _index The insertion index position. NOTE: Unlike the
2215  * Rexx version, the index is the position where
2216  * this value will be inserted, not the index of
2217  * where it is inserted after.
2218  *
2219  * @return The index of the inserted item.
2220  */
2221 size_t RexxArray::insert(RexxObject *value, size_t _index)
2222 {
2223  openGap(_index, 1); // open an appropriate sized gap in the array
2224  this->put(value, _index); // add the inserted element */
2225  return _index; // return the index of the insertion
2226 }
2227 
2228 
2229 /**
2230  * Insert an element into the array, shifting all of the
2231  * existing elements at the inserted position and adjusting
2232  * the size accordingly.
2233  *
2234  * @param value The value to insert (can be OREF_NULL to just open a new slot)
2235  * @param _index The insertion index position.
2236  *
2237  * @return The index of the inserted item.
2238  */
2240 {
2241  RexxObject *result = get(_index); // save the return value
2242  closeGap(_index, 1); // close up the gap for the deleted item
2243  // return .nil if there's nothing at that position
2244  return result == OREF_NULL ? TheNilObject : result;
2245 }
2246 
2247 
2248 void * RexxArray::operator new(size_t size,
2249  size_t items, /* items in the array */
2250  RexxObject **first ) /* array of items to fill array */
2251 /******************************************************************************/
2252 /* Quick creation of an argument array */
2253 /******************************************************************************/
2254 {
2255  RexxArray *newArray = new_array(items); /* get a new array */
2256  if (items != 0) /* not a null array? */
2257  {
2258  /* copy the references in */
2259  memcpy(newArray->data(), first, (sizeof(RexxObject *) * items));
2260  // we need to make sure the lastElement field is set to the
2261  // new arg position.
2262  for (;items > 0; items--)
2263  {
2264  if (newArray->get(items) != OREF_NULL)
2265  {
2266  newArray->lastElement = items;
2267  break;
2268  }
2269  }
2270  }
2271  return newArray; /* return the new array */
2272 }
2273 
2274 void *RexxArray::operator new(size_t size, RexxObject **args, size_t argCount, RexxClass *arrayClass)
2275 /******************************************************************************/
2276 /* Function: Rexx level creation of an ARRAY object */
2277 /******************************************************************************/
2278 {
2279  if (argCount == 0)
2280  {
2281  /* If no argument is passed */
2282  /* create an empty array. */
2283  RexxArray *temp = new ((size_t)0, ARRAY_DEFAULT_SIZE, arrayClass) RexxArray;
2284  ProtectedObject p(temp);
2285  temp->sendMessage(OREF_INIT); /* call any rexx init's */
2286  return temp;
2287  }
2288 
2289  /* Special case for 1-dimensional */
2290  if (argCount == 1)
2291  {
2292  RexxObject *current_dim = args[0];
2293  // specified as an array of dimensions?
2294  // this gets special handling
2295  if (current_dim != OREF_NULL && isOfClass(Array, current_dim))
2296  {
2297  return RexxArray::createMultidimensional(((RexxArray *)current_dim)->data(), ((RexxArray *)current_dim)->items(), arrayClass);
2298  }
2299  /* Make sure it's an integer */
2300  wholenumber_t total_size = current_dim->requiredNonNegative(OREF_positional, ARG_ONE, number_digits());
2301  if (total_size < 0)
2302  {
2304  }
2305 
2306  if ((size_t)total_size >= MAX_FIXEDARRAY_SIZE)
2307  {
2309  }
2310 
2311  /* Note: The following will leave the dimension field set to OREF_NULL, */
2312  /* which is what we want (it will be done by array_init above). */
2313  /* Create new array of approp. size. */
2314 
2315  RexxArray *temp = (RexxArray *)new_externalArray(total_size, arrayClass);
2316  ProtectedObject p(temp);
2317  if (total_size == 0)
2318  { /* Creating 0 sized array? */
2319  /* Yup, setup a Dimension array */
2320  /* single Dimension, Mark so */
2321  /* can't change Dimensions. */
2322  OrefSet(temp, temp->dimensions, new_array(IntegerZero));
2323  }
2324  temp->sendMessage(OREF_INIT); /* call any rexx init's */
2325  return temp; /* Return the new array. */
2326  }
2327 
2328  return RexxArray::createMultidimensional(args, argCount, arrayClass);
2329 }
2330 
2331 /**
2332  * Helper routine for creating a multidimensional array.
2333  *
2334  * @param dims Pointer to an array of pointers to dimension objects.
2335  * @param count the number of dimensions to create
2336  *
2337  * @return The created array
2338  */
2340 {
2341  /* Working with a multi-dimension */
2342  /* array, so get a dimension arr */
2343  RexxArray *dim_array = (RexxArray *)new_array(count);
2344  ProtectedObject d(dim_array);
2345  size_t total_size = 1; /* Set up for multiplication */
2346  for (size_t i = 0; i < count; i++)
2347  {
2348  /* make sure current parm is inte */
2349  RexxObject *current_dim = (RexxInteger *)dims[i];
2350  if (current_dim == OREF_NULL) /* was this one omitted? */
2351  {
2352  missingArgument(OREF_positional, i+1); /* must have this value */
2353  }
2354  /* get the long value */
2355  size_t cur_size = current_dim->requiredNonNegative(OREF_positional, (int)(i+1));
2356  /* going to do an overflow? */
2357  if (cur_size != 0 && ((MAX_FIXEDARRAY_SIZE / cur_size) < total_size))
2358  {
2359  /* this is an error */
2361  }
2362  total_size *= cur_size; /* keep running total size */
2363  /* Put integer object into curren */
2364  /* dimension array position */
2365  dim_array->put(new_integer(cur_size), i+1);
2366  }
2367  /* Make sure flattened array isn't */
2368  /* too big. */
2369  if (total_size >= MAX_FIXEDARRAY_SIZE)
2370  {
2372  }
2373  /* Create the new array */
2374  RexxArray *temp = (RexxArray *)new_externalArray(total_size, arrayClass);
2375  /* put dimension array in new arr */
2376  OrefSet(temp, temp->dimensions, dim_array);
2377  ProtectedObject p(temp);
2378  temp->sendMessage(OREF_INIT); /* call any rexx init's */
2379  return temp;
2380 }
2381 
2382 
2383 /**
2384  * The merge sort routine. This will partition the data in to
2385  * two sections, mergesort each partition, then merge the two
2386  * partitions together.
2387  *
2388  * @param comparator The comparator object used for the compares.
2389  * @param working The working array (same size as the sorted array).
2390  * @param left The left bound of the partition.
2391  * @param right The right bounds of the parition
2392  * (inclusive).
2393  */
2394 void RexxArray::mergeSort(BaseSortComparator &comparator, RexxArray *working, size_t left, size_t right)
2395 {
2396  size_t len = right - left + 1; // total size of the range
2397  // use insertion sort for small arrays
2398  if (len <= 7) {
2399  for (size_t i = left + 1; i <= right; i++) {
2400  RexxObject *current = get(i);
2401  RexxObject *prev = get(i - 1);
2402  if (comparator.compare(current, prev) < 0) {
2403  size_t j = i;
2404  do {
2405  put(prev, j--);
2406  } while (j > left && comparator.compare(current, prev = get(j - 1)) < 0);
2407  put(current, j);
2408  }
2409  }
2410  return;
2411  }
2412 
2413  size_t mid = (right + left) / 2;
2414  mergeSort(comparator, working, left, mid);
2415  mergeSort(comparator, working, mid + 1, right);
2416  merge(comparator, working, left, mid + 1, right);
2417 }
2418 
2419 
2420 /**
2421  * Perform the merge operation on two partitions.
2422  *
2423  * @param comparator The comparator used to produce the ordering.
2424  * @param working The temporary working storage.
2425  * @param left The left bound of the range.
2426  * @param mid The midpoint of the range. This merges the two partitions
2427  * (left, mid - 1) and (mid, right).
2428  * @param right The right bound of the array.
2429  */
2430 void RexxArray::merge(BaseSortComparator &comparator, RexxArray *working, size_t left, size_t mid, size_t right)
2431 {
2432  size_t leftEnd = mid - 1;
2433  // merging
2434 
2435  // if arrays are already sorted - no merge
2436  if (comparator.compare(get(leftEnd), get(mid)) <= 0) {
2437  return;
2438  }
2439 
2440  size_t leftCursor = left;
2441  size_t rightCursor = mid;
2442  size_t workingPosition = left;
2443 
2444  // use merging with exponential search
2445  do
2446  {
2447  RexxObject *fromVal = get(leftCursor);
2448  RexxObject *rightVal = get(rightCursor);
2449  // if the left value is the smaller one, so we try to find the
2450  // insertion point of the right value into the left side of the
2451  // the array
2452  if (comparator.compare(fromVal, rightVal) <= 0)
2453  {
2454  // try to find an insertion point in the remaining left-hand elements
2455  size_t leftInsertion = find(comparator, rightVal, -1, leftCursor + 1, leftEnd);
2456  // we start copying with the left-hand bound up to the insertion point
2457  size_t toCopy = leftInsertion - leftCursor + 1;
2458  arraycopy(this, leftCursor, working, workingPosition, toCopy);
2459  workingPosition += toCopy;
2460  // add the inserted position
2461  working->put(rightVal, workingPosition++);
2462  // now we've added this
2463  rightCursor++;
2464  // step over the section we just copied...which might be
2465  // all of the remaining section
2466  leftCursor = leftInsertion + 1;
2467  }
2468  else
2469  {
2470  // find the insertion point of the left value into the remaining right
2471  // hand section
2472  size_t rightInsertion = find(comparator, fromVal, 0, rightCursor + 1, right);
2473  size_t toCopy = rightInsertion - rightCursor + 1;
2474  arraycopy(this, rightCursor, working, workingPosition, toCopy);
2475  workingPosition += toCopy;
2476  // insert the right-hand value
2477  working->put(fromVal, workingPosition++);
2478  leftCursor++;
2479  rightCursor = rightInsertion + 1;
2480  }
2481  } while (right >= rightCursor && mid > leftCursor);
2482 
2483  // copy rest of array. If we've not used up the left hand side,
2484  // we copy that. Otherwise, there are items on the right side
2485  if (leftCursor < mid)
2486  {
2487  arraycopy(this, leftCursor, working, workingPosition, mid - leftCursor);
2488  }
2489  else
2490  {
2491  arraycopy(this, rightCursor, working, workingPosition, right - rightCursor + 1);
2492  }
2493 
2494  // finally, copy everything back into the the target array.
2495  arraycopy(working, left, this, left, right - left + 1);
2496 }
2497 
2498 
2499 /**
2500  * copy segments of one array into another.
2501  *
2502  * @param source The source array
2503  * @param start The starting index of the source copy
2504  * @param target The target array
2505  * @param index The target copy index
2506  * @param count The number of items to count.
2507  */
2508 void RexxArray::arraycopy(RexxArray *source, size_t start, RexxArray *target, size_t index, size_t count)
2509 {
2510  for (size_t i = start; i < start + count; i++)
2511  {
2512  target->put(source->get(i), index++);
2513  }
2514 }
2515 
2516 
2517 /**
2518  * Finds the place in the given range of specified sorted array, where the
2519  * element should be inserted for getting sorted array. Uses exponential
2520  * search algorithm.
2521  *
2522  * @param comparator The comparator used to compare pairs of elements.
2523  * @param val object to be inserted
2524  * @param limit possible values 0,-1. "-1" - val is located
2525  * at index more then elements equals to val.
2526  * "0" - val is located at index less then
2527  * elements equals to val.
2528  * @param left The left bound of the insert operation.
2529  * @param right The right bound for the insert (inclusive)
2530  *
2531  * @return The insertion point.
2532  */
2533 size_t RexxArray::find(BaseSortComparator &comparator, RexxObject *val, int limit, size_t left, size_t right)
2534 {
2535  size_t checkPoint = left;
2536  size_t delta = 1;
2537  while (checkPoint <= right)
2538  {
2539  // if this is too big, then we're moving to the right
2540  if (comparator.compare(val, get(checkPoint)) > limit)
2541  {
2542  // the left bound is at least this
2543  left = checkPoint + 1;
2544  }
2545  else
2546  {
2547  // we've found a right limit. We can stop scanning here
2548  right = checkPoint - 1;
2549  break;
2550  }
2551  // step the delta amount
2552  checkPoint += delta;
2553  // and double the movement amount
2554  delta = delta * 2;
2555  }
2556  // we should have now limited the bounds for the insertion point
2557  // now start in the middle and shrink the range with each comparison
2558  while (left <= right)
2559  {
2560  // start in the middle of the current range
2561  checkPoint = (left + right) / 2;
2562  if (comparator.compare(val, get(checkPoint)) > limit)
2563  {
2564  // pull in the left end of the range
2565  left = checkPoint + 1;
2566  }
2567  else
2568  {
2569  // chop the right range
2570  right = checkPoint - 1;
2571  }
2572  }
2573 
2574  // the left bound is the insertion point
2575  return left - 1;
2576 }
2577 
2578 
2579 /**
2580  * Sort elements of the array in place, using a stable merge
2581  * sort.
2582  *
2583  * @return Returns the same array, with the elements sorted.
2584  */
2586 {
2587  size_t count = items();
2588  if (count == 0) // if the count is zero, sorting is easy!
2589  {
2590  return this;
2591  }
2592 
2593  // make sure this is a non-sparse array. Checking up front means we don't
2594  // need to check on each compare operation.
2595  for (size_t i = 1; i <= count; i++)
2596  {
2597  if (get(i) == OREF_NULL)
2598  {
2600  }
2601  }
2602 
2603  // the merge sort requires a temporary scratch area for the sort.
2604  RexxArray *working = new_array(count);
2605  ProtectedObject p(working);
2606 
2607  BaseSortComparator comparator;
2608 
2609  // go do the quick sort
2610  mergeSort(comparator, working, 1, count);
2611  return this;
2612 }
2613 
2614 
2615 /**
2616  * Sort elements of the array in place, using a stable merge
2617  * sort.
2618  *
2619  * @return Returns the same array, with the elements sorted.
2620  */
2622 {
2623  requiredArgument(comparator, OREF_positional, ARG_ONE);
2624 
2625  size_t count = items();
2626  if (count <= 1) // if the count is zero, sorting is easy!
2627  {
2628  return this;
2629  }
2630 
2631  // make sure this is a non-sparse array. Checking up front means we don't
2632  // need to check on each compare operation.
2633  for (size_t i = 1; i <= count; i++)
2634  {
2635  if (get(i) == OREF_NULL)
2636  {
2638  }
2639  }
2640 
2641  // the merge sort requires a temporary scratch area for the sort.
2642  RexxArray *working = new_array(count);
2643  ProtectedObject p(working);
2644 
2645  WithSortComparator c(comparator);
2646 
2647  // go do the quick sort
2648  mergeSort(c, working, 1, count);
2649  return this;
2650 }
2651 
2652 
2653 void * RexxArray::operator new(size_t size, RexxObject *first)
2654 /******************************************************************************/
2655 /* Function: Create an array with 1 element (new_array1) */
2656 /******************************************************************************/
2657 {
2658  RexxArray *aref;
2659 
2660  aref = (RexxArray *)new_array(1);
2661  aref->put(first, 1);
2662 
2663  return aref;
2664 }
2665 
2666 void * RexxArray::operator new(size_t size, RexxObject *first, RexxObject *second)
2667 {
2668  RexxArray *aref;
2669 
2670  aref = new_array(2);
2671  aref->put(first, 1);
2672  aref->put(second, 2);
2673  return aref;
2674 }
2675 
2676 void * RexxArray::operator new(size_t size,
2677  RexxObject *first,
2678  RexxObject *second,
2679  RexxObject *third)
2680 /******************************************************************************/
2681 /* Function: Create an array with 3 elements (new_array3) */
2682 /******************************************************************************/
2683 {
2684  RexxArray *aref;
2685 
2686  aref = new_array(3);
2687  aref->put(first, 1);
2688  aref->put(second, 2);
2689  aref->put(third, 3);
2690 
2691  return aref;
2692 }
2693 
2694 void * RexxArray::operator new(size_t size,
2695  RexxObject *first,
2696  RexxObject *second,
2697  RexxObject *third,
2698  RexxObject *fourth)
2699 /******************************************************************************/
2700 /* Function: Create an array with 4 elements (new_array4) */
2701 /******************************************************************************/
2702 {
2703  RexxArray *aref;
2704 
2705  aref = new_array(4);
2706  aref->put(first, 1);
2707  aref->put(second, 2);
2708  aref->put(third, 3);
2709  aref->put(fourth, 4);
2710 
2711  return aref;
2712 }
2713 
2714 void * RexxArray::operator new(size_t size,
2715  RexxObject *first,
2716  RexxObject *second,
2717  RexxObject *third,
2718  RexxObject *fourth,
2719  RexxObject *fifth)
2720 /******************************************************************************/
2721 /* Function: Create an array with 5 elements (new_array5) */
2722 /******************************************************************************/
2723 {
2724  RexxArray *aref;
2725 
2726  aref = new_array(5);
2727  aref->put(first, 1);
2728  aref->put(second, 2);
2729  aref->put(third, 3);
2730  aref->put(fourth, 4);
2731  aref->put(fifth, 5);
2732 
2733  return aref;
2734 }
2735 
2736 void *RexxArray::operator new(size_t newSize, size_t size, size_t maxSize, RexxClass *arrayClass)
2737 /******************************************************************************/
2738 /* Function: Low level array creation */
2739 /******************************************************************************/
2740 {
2741  size_t bytes;
2742  RexxArray *newArray;
2743  /* is hintsize lower than minimal */
2744  if (maxSize <= ARRAY_MIN_SIZE)
2745  { /* allocation array size? */
2746  maxSize = ARRAY_MIN_SIZE; /* yes, we will actually min size */
2747  }
2748  // if the max is smaller than the size, just use the max size.
2749  if (maxSize < size)
2750  {
2751  maxSize = size;
2752  }
2753  /* compute size of new array obj */
2754  bytes = newSize + (sizeof(RexxObject *) * (maxSize - 1));
2755  /* Create the new array */
2756  newArray = (RexxArray *)new_object(bytes);
2757  /* Give it array behaviour. */
2758  newArray->setBehaviour(arrayClass->getInstanceBehaviour());
2759 
2760  newArray->arraySize = size;
2761  newArray->maximumSize = maxSize;
2762  /* no expansion yet, use ourself */
2763  newArray->expansionArray = newArray;
2764  /* moved _after_ setting hashvalue, otherwise the uninit table will not be*/
2765  /* able to find the new array object again later! */
2766  if (arrayClass->hasUninitDefined())
2767  {/* does object have an UNINT method */
2768  ProtectedObject p(newArray);
2769  /* require new REXX objects */
2770  newArray->hasUninit(); /* Make sure everyone is notified. */
2771  }
2772  return newArray; /* return the new array to caller */
2773 }
2774 
2775 RexxObject * RexxArray::newRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
2776 /******************************************************************************/
2777 /* Function: Exported ARRAY NEW method */
2778 /******************************************************************************/
2779 {
2780  return new (arguments, (argCount + (2 * named_argCount)), (RexxClass *) this) RexxArray;
2781 }
2782 
2783 RexxObject *RexxArray::of(RexxObject **args, size_t argCount, size_t named_argCount)
2784 /******************************************************************************/
2785 /* Function: Exported REXX OF method */
2786 /******************************************************************************/
2787 {
2788  RexxArray *newArray; /* new array item */
2789  size_t i; /* loop index */
2790  RexxObject*item; /* individual array item */
2791 
2792  // TODO
2793  // The named arguments could be added to the returned array.
2794 
2795  /* is array obj to be from internal */
2796  if (TheArrayClass != (RexxClass *)this)
2797  {
2798  /* nope, better create properly */
2799  ProtectedObject result;
2800  /* send new to actual class. */
2801  this->sendMessage(OREF_NEW, new_integer(argCount), result);
2802  newArray = (RexxArray *)result;
2803  /* For each argument to of, send a */
2804  /* put message */
2805  for (i = 0; i < argCount; i++)
2806  {
2807  item = args[i]; /* get the item */
2808  if (item != OREF_NULL) /* have a real item here? */
2809  {
2810  /* place it in the target array */
2811  newArray->sendMessage(OREF_PUT, item, new_integer(i+1));
2812  }
2813  }
2814  return newArray;
2815  }
2816  else
2817  {
2818  newArray = new (argCount, args) RexxArray;
2819  if (argCount == 0)
2820  { /* creating 0 sized array? */
2821  /* Yup, setup a Dimension array */
2822  /* single Dimension, Mark so */
2823  /* can't change Dimensions. */
2824  OrefSet(newArray, newArray->dimensions, new_array(IntegerZero));
2825  }
2826  /* argument array is exactly what */
2827  /* we want, so just return it */
2828  return newArray;
2829  }
2830 
2831 }
2832 
2833 
2835 {
2836  return first->compareTo(second);
2837 }
2838 
2839 
2841 {
2842  ProtectedObject result;
2843  comparator->sendMessage(OREF_COMPARE, first, second, result);
2844  if ((RexxObject *)result == OREF_NULL)
2845  {
2847  }
2848 
2849  wholenumber_t comparison;
2850  if (!((RexxObject *)result)->numberValue(comparison, Numerics::DEFAULT_DIGITS))
2851  {
2853  }
2854  return comparison;
2855 }
void reportException(wholenumber_t error)
void missingArgument(RexxString *kind, size_t argumentPosition)
void copyElements(COPYELEMENTPARM *parm, size_t newDimension)
#define min(a, b)
Definition: ArrayClass.cpp:82
#define ExtendUpper
Definition: ArrayClass.hpp:52
#define RaiseBoundsUpper
Definition: ArrayClass.hpp:48
RexxArray * new_externalArray(size_t s, RexxClass *c)
Definition: ArrayClass.hpp:247
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
#define RaiseBoundsTooMany
Definition: ArrayClass.hpp:50
#define RaiseBoundsInvalid
Definition: ArrayClass.hpp:49
RexxInteger * new_integer(wholenumber_t v)
size_t number_digits()
Definition: Numerics.hpp:155
#define OREF_NULL
Definition: RexxCore.h:60
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define TheNullArray
Definition: RexxCore.h:183
#define IntegerOne
Definition: RexxCore.h:190
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheTrueObject
Definition: RexxCore.h:186
const int ARG_TWO
Definition: RexxCore.h:81
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheArrayClass
Definition: RexxCore.h:147
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
const int ARG_ONE
Definition: RexxCore.h:80
#define IntegerZero
Definition: RexxCore.h:189
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:291
#define TheMutableBufferClass
Definition: RexxCore.h:162
#define Error_Incorrect_method_option
#define Error_Execution_sparse_array
#define Error_No_result_object_message
#define Error_Incorrect_method_array_too_big
#define Error_Incorrect_method_section
#define Error_Incorrect_method_minsub
#define Error_Incorrect_method_array_dimension
#define Error_Incorrect_method_maxarg
#define Error_Incorrect_method_array
#define Error_Incorrect_method_minarg
#define Error_Invalid_whole_number_compare
#define Error_Incorrect_method_noarg
#define Error_Incorrect_method_maxsub
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#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
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
RexxSupplier * new_supplier(RexxArray *c, RexxArray *f)
virtual wholenumber_t compare(RexxObject *first, RexxObject *second)
static const wholenumber_t MAX_WHOLENUMBER
Definition: Numerics.hpp:62
static wholenumber_t minVal(wholenumber_t n1, wholenumber_t n2)
Definition: Numerics.hpp:116
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
RexxObject * lastItem()
RexxObject ** slotAddress(size_t index)
Definition: ArrayClass.hpp:232
static const size_t ARRAY_DEFAULT_SIZE
Definition: ArrayClass.hpp:222
RexxObject * isEmpty()
Definition: ArrayClass.cpp:301
static const size_t ARRAY_MIN_SIZE
Definition: ArrayClass.hpp:221
RexxObject * getRexx(RexxObject **, size_t, size_t)
Definition: ArrayClass.cpp:506
size_t findSingleIndexItem(RexxObject *item)
static const size_t MAX_FIXEDARRAY_SIZE
Definition: ArrayClass.hpp:236
void flatten(RexxEnvelope *)
Definition: ArrayClass.cpp:179
static void createInstance()
Definition: ArrayClass.cpp:95
bool hasIndexNative(size_t)
size_t getDimension()
Definition: ArrayClass.cpp:693
void live(size_t)
Definition: ArrayClass.cpp:146
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxObject * insertRexx(RexxObject *_value, RexxObject *index)
Definition: ArrayClass.cpp:344
void closeGap(size_t index, size_t elements)
Definition: ArrayClass.cpp:447
RexxArray * dimensions
Definition: ArrayClass.hpp:241
RexxObject * of(RexxObject **, size_t, size_t)
RexxObject * supplier(RexxObject *maxItems=OREF_NULL)
Definition: ArrayClass.cpp:786
size_t find(BaseSortComparator &comparator, RexxObject *val, int bnd, size_t left, size_t right)
static RexxClass * classInstance
Definition: ArrayClass.hpp:218
RexxObject * copy()
Definition: ArrayClass.cpp:122
RexxObject * remove(size_t)
Definition: ArrayClass.cpp:593
bool hasIndexApi(size_t)
Definition: ArrayClass.cpp:576
static void arraycopy(RexxArray *source, size_t start, RexxArray *target, size_t index, size_t count)
static RexxArray * nullArray
Definition: ArrayClass.hpp:219
void resize()
RexxObject * getApi(size_t pos)
Definition: ArrayClass.cpp:536
size_t indexOf(RexxObject *)
size_t maximumSize
Definition: ArrayClass.hpp:239
RexxObject * firstRexx()
RexxInteger * available(size_t position)
Definition: ArrayClass.cpp:834
RexxInteger * sizeRexx()
size_t lastElement
Definition: ArrayClass.hpp:240
RexxObject * putRexx(RexxObject **, size_t, size_t)
Definition: ArrayClass.cpp:228
RexxObject * join(RexxArray *)
RexxObject * newRexx(RexxObject **, size_t, size_t)
RexxArray * allItems(RexxObject *maxItems=OREF_NULL)
void openGap(size_t index, size_t elements)
Definition: ArrayClass.cpp:412
bool isMultiDimensional()
Definition: ArrayClass.hpp:211
size_t arraySize
Definition: ArrayClass.hpp:238
RexxObject * nextRexx(RexxObject **, size_t, size_t)
RexxArray * allIndexes(RexxObject *maxIndexes=OREF_NULL)
RexxObject * deleteRexx(RexxObject *index)
Definition: ArrayClass.cpp:385
RexxObject * convertIndex(size_t idx)
size_t append(RexxObject *)
Definition: ArrayClass.cpp:485
RexxObject * appendRexx(RexxObject *)
Definition: ArrayClass.cpp:314
RexxObject * itemsRexx()
Definition: ArrayClass.cpp:685
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * empty()
Definition: ArrayClass.cpp:273
void ensureSpace(size_t newSize)
RexxObject * index(RexxObject *)
size_t dataSize()
Definition: ArrayClass.hpp:233
void setExpansion(RexxObject *expansion)
Definition: ArrayClass.cpp:826
size_t insert(RexxObject *_value, size_t index)
RexxArray * stableSortRexx()
RexxObject * sectionSubclass(size_t, size_t)
RexxObject * removeItem(RexxObject *)
bool isSingleDimensional()
Definition: ArrayClass.hpp:212
RexxArray * section(size_t, size_t)
RexxObject * hasItem(RexxObject *)
void liveGeneral(int reason)
Definition: ArrayClass.cpp:164
void putApi(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:554
RexxObject * deleteItem(size_t index)
RexxObject * removeRexx(RexxObject **, size_t, size_t)
Definition: ArrayClass.cpp:626
RexxObject * objects[1]
Definition: ArrayClass.hpp:243
size_t lastIndex()
RexxObject * lastRexx()
RexxObject * fill(RexxObject *)
Definition: ArrayClass.cpp:253
size_t items()
Definition: ArrayClass.cpp:663
RexxObject * getDimensions()
Definition: ArrayClass.cpp:714
RexxArray * stableSortWithRexx(RexxObject *comparator)
bool validateIndex(RexxObject **, size_t, size_t, size_t, stringsize_t &)
Definition: ArrayClass.cpp:843
RexxObject * dimension(RexxObject *)
Definition: ArrayClass.cpp:729
RexxArray * extend(size_t)
RexxArray * makeArray()
RexxObject * hasIndexRexx(RexxObject **, size_t, size_t)
RexxObject * sectionRexx(RexxObject *, RexxObject *)
RexxObject * previousRexx(RexxObject **, size_t, size_t)
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxArray * extendMulti(RexxObject **, size_t, size_t)
static RexxArray * createMultidimensional(RexxObject **dims, size_t count, RexxClass *)
RexxString * toString(RexxString *, RexxString *)
void mergeSort(BaseSortComparator &comparator, RexxArray *working, size_t left, size_t right)
RexxArray * expansionArray
Definition: ArrayClass.hpp:242
RexxObject ** data()
Definition: ArrayClass.hpp:204
void merge(BaseSortComparator &comparator, RexxArray *working, size_t left, size_t mid, size_t right)
RexxObject * indexToArray(size_t idx)
RexxObject * firstItem()
void shrink(size_t)
RexxClass * getOwningClass()
void setBehaviour(RexxBehaviour *b)
virtual RexxObject * getValue(RexxActivation *)
RexxBehaviour * behaviour
void reSize(RexxObject *, size_t)
RexxMutableBuffer * append(RexxObject *)
RexxString * makeString()
stringsize_t requiredPositive(RexxString *kind, size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
RexxMessage * start(RexxObject **, size_t, size_t)
virtual wholenumber_t compareTo(RexxObject *)
stringsize_t requiredNonNegative(RexxString *kind, size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
RexxString * primitiveMakeString()
RexxString * makeString()
bool equalValue(RexxObject *other)
RexxObject * copy()
RexxString * requiredString(RexxString *kind, size_t)
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxObject * newRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
RexxObject * init()
const char * getStringData()
virtual wholenumber_t compare(RexxObject *first, RexxObject *second)
RexxObject * comparator
Definition: ArrayClass.hpp:96
ssize_t wholenumber_t
Definition: rexx.h:230
size_t stringsize_t
Definition: rexx.h:228
RexxArray * oldDimArray
Definition: ArrayClass.hpp:59
RexxObject ** startOld
Definition: ArrayClass.hpp:64
size_t firstChangedDimension
Definition: ArrayClass.hpp:56
size_t skipElements
Definition: ArrayClass.hpp:62
RexxArray * newDimArray
Definition: ArrayClass.hpp:58
size_t deltaDimSize
Definition: ArrayClass.hpp:60
RexxObject ** startNew
Definition: ArrayClass.hpp:63
size_t copyElements
Definition: ArrayClass.hpp:61
RexxArray * newArray
Definition: ArrayClass.hpp:57
#define line_end