1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11 #include <stdarg.h>
12 #include <string.h>
13 #include "arrayClass.h"
14
15 /*
16 * size multipliers for type, category
17 */
18
19 /* XXX */
20 int
DXTypeSize(Type t)21 DXTypeSize(Type t)
22 {
23 switch (t) {
24 case TYPE_BYTE: return sizeof(byte);
25 case TYPE_UBYTE: return sizeof(ubyte);
26 case TYPE_SHORT: return sizeof(short);
27 case TYPE_USHORT: return sizeof(ushort);
28 case TYPE_INT: return sizeof(int);
29 case TYPE_UINT: return sizeof(uint);
30 case TYPE_HYPER: return 8;
31 case TYPE_FLOAT: return sizeof(float);
32 case TYPE_DOUBLE: return sizeof(double);
33 case TYPE_STRING: return sizeof(char);
34 default:
35 return DXSetError(ERROR_BAD_PARAMETER, "unknown Type %d", t);
36 }
37 }
38
39 int
DXCategorySize(Category category)40 DXCategorySize(Category category)
41 {
42 switch(category) {
43 case CATEGORY_REAL: return 1;
44 case CATEGORY_COMPLEX: return 2;
45 case CATEGORY_QUATERNION: return 4;
46 default:
47 return DXSetError(ERROR_BAD_PARAMETER,
48 "unknown Category %d", category);
49 }
50 }
51
52
53 /*
54 * new array, shape specified as a vector
55 */
56
57 Array
_dxf_NewArrayV(Type type,Category category,int rank,int * shape,struct array_class * class)58 _dxf_NewArrayV(Type type, Category category, int rank, int *shape,
59 struct array_class *class)
60 {
61 int i;
62 Array a = (Array) _dxf_NewObject((struct object_class *)class);
63 if (!a)
64 return NULL;
65
66 /* specified info */
67 a->type = type;
68 a->category = category;
69 a->rank = rank;
70 if (shape && rank!=0) {
71 a->shape = rank>NLSHAPE?
72 (int*)DXAllocate(rank*sizeof(*shape)) : a->lshape;
73 if (!a->shape)
74 return NULL;
75 for (i=0; i<rank; i++)
76 a->shape[i] = shape[i];
77 } else if (rank != 0) {
78 DXSetError(ERROR_BAD_PARAMETER,
79 "rank=%d but shape was not specified in DXNewArray", rank);
80 return NULL;
81 } else
82 a->shape = NULL;
83
84 /* size is derived */
85 a->size = DXTypeSize(type) * DXCategorySize(category);
86 if (!a->size)
87 return NULL;
88 for (i=0; i<rank; i++)
89 a->size *= shape[i];
90 if (!a->size)
91 DXErrorReturn(ERROR_BAD_PARAMETER, "extent specified as 0 in DXNewArray");
92 a->items = 0;
93 a->data = NULL;
94 DXcreate_lock(&a->inprogress, "in progress");
95
96 return a;
97 }
98
99
100 Array
DXNewArrayV(Type type,Category category,int rank,int * shape)101 DXNewArrayV(Type type, Category category, int rank, int *shape)
102 {
103 return _dxf_NewArrayV(type, category, rank, shape, &_dxdarray_class);
104 }
105
106
107 Array
DXNewArray(Type type,Category category,int rank,...)108 DXNewArray(Type type, Category category, int rank, ...)
109 {
110 int shape[100];
111 int i;
112 va_list arg;
113
114 ASSERT(rank<100);
115
116 /* collect args */
117 va_start(arg,rank);
118 for (i=0; i<rank; i++)
119 shape[i] = va_arg(arg, int);
120 va_end(arg);
121
122 /* call V version */
123 return DXNewArrayV(type, category, rank, shape);
124 }
125
126
127 Array
DXGetArrayInfo(Array a,int * items,Type * type,Category * category,int * rank,int * shape)128 DXGetArrayInfo(Array a, int *items, Type *type, Category *category,
129 int *rank, int *shape)
130 {
131 int i;
132
133 CHECK(a, CLASS_ARRAY);
134
135 if (items)
136 *items = a->items;
137 if (type)
138 *type = a->type;
139 if (category)
140 *category = a->category;
141 if (rank)
142 *rank = a->rank;
143 if (shape)
144 for (i=0; i<a->rank; i++)
145 shape[i] = a->shape[i];
146
147 return a;
148 }
149
150
151 Object
_dxfArray_GetType(Array a,Type * t,Category * c,int * rank,int * shape)152 _dxfArray_GetType(Array a, Type *t, Category *c, int *rank, int *shape)
153 {
154 int i;
155
156 if (t)
157 *t = a->type;
158 if (c)
159 *c = a->category;
160 if (rank)
161 *rank = a->rank;
162 if (shape)
163 for (i=0; i<a->rank; i++)
164 shape[i] = a->shape[i];
165
166 return (Object) a;
167 }
168
169
DXGetItemSize(Array a)170 int DXGetItemSize(Array a)
171 {
172 CHECK(a, CLASS_ARRAY);
173 return a->size;
174 }
175
176
177 Array
DXTypeCheckV(Array a,Type type,Category category,int rank,int * shape)178 DXTypeCheckV(Array a, Type type, Category category, int rank, int *shape)
179 {
180 Type t;
181 Category c;
182 int i, r, s[100];
183
184 ASSERT(rank<100);
185
186 if (!DXGetArrayInfo(a, NULL, &t, &c, &r, NULL))
187 return NULL;
188 if (t!=type || c!=category || r!=rank)
189 return NULL;
190
191 if (!DXGetArrayInfo(a, NULL, NULL, NULL, NULL, s))
192 return NULL;
193 if (shape)
194 for (i=0; i<rank; i++)
195 if (s[i]!=shape[i])
196 return NULL;
197
198 return a;
199 }
200
201
202 Array
DXTypeCheck(Array a,Type type,Category category,int rank,...)203 DXTypeCheck(Array a, Type type, Category category, int rank, ...)
204 {
205 int shape[100];
206 int i;
207 va_list arg;
208
209 ASSERT(rank<100);
210
211 /* collect args */
212 va_start(arg,rank);
213 for (i=0; i<rank; i++)
214 shape[i] = va_arg(arg, int);
215 va_end(arg);
216
217 /* call V version */
218 return DXTypeCheckV(a, type, category, rank, shape);
219 }
220
221
222 Pointer
_dxfArray_GetArrayData(Array a)223 _dxfArray_GetArrayData(Array a)
224 {
225 CHECK(a, CLASS_ARRAY);
226
227 /* always return something */
228 if (!a->data)
229 DXAllocateArray(a, 0);
230
231 return a->data;
232 }
233
234
235
236 Pointer
DXGetArrayDataLocal(Array a)237 DXGetArrayDataLocal(Array a)
238 {
239 Pointer data;
240
241 CHECK(a, CLASS_ARRAY);
242 data = DXGetArrayData(a);
243 #if DXD_HAS_LOCAL_MEMORY
244 {
245 int n;
246 Pointer local;
247 if (!data)
248 return NULL;
249 /* XXX - copy, record local reference */
250 n = a->size * a->items;
251 local = DXAllocateLocal(n);
252 if (!local) {
253 DXResetError();
254 DXWarning("no room for array of %d bytes in local memory", n);
255 return data;
256 }
257 memcpy(local, data, n);
258 return local;
259 }
260 #else
261 return data;
262 #endif
263 }
264
265
266
267 Array
DXFreeArrayDataLocal(Array a,Pointer data)268 DXFreeArrayDataLocal(Array a, Pointer data)
269 {
270 CHECK(a, CLASS_ARRAY);
271 #if DXD_HAS_LOCAL_MEMORY
272 if (data!=a->data)
273 DXFree(data);
274 #endif
275 return a;
276 }
277
278
279 Error
_dxfArray_Delete(Array a)280 _dxfArray_Delete(Array a)
281 {
282 if (a->shape != a->lshape)
283 DXFree((Pointer)(a->shape));
284 if (a->data != (Pointer)a->ldata)
285 DXFree((Pointer)(a->data));
286 return OK;
287 }
288
289
290 Object
_dxfArray_Copy(Array old,enum _dxd_copy copy)291 _dxfArray_Copy(Array old, enum _dxd_copy copy)
292 {
293 if (copy==COPY_DATA)
294 DXErrorReturn(ERROR_BAD_PARAMETER, "copying data is not implemented");
295 return (Object)old;
296 }
297
298
299 Array
DXAddArrayData(Array a,int start,int n,Pointer data)300 DXAddArrayData(Array a, int start, int n, Pointer data)
301 {
302 CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */
303
304 /* expand if necessary */
305 /* second test guarantees that we allocate a buffer */
306 if (start+n > a->allocated || a->allocated==0) {
307 /* allocate 25% extra iff this is a realloc */
308 int alloc = (a->allocated? (start+n)*5/4 : start+n);
309 if (!DXAllocateArray(a, alloc))
310 return NULL;
311 }
312
313 /* copy the data */
314 if (data)
315 memcpy((char *)(a->data)+start*a->size, data, n*a->size);
316
317 /* record the new number of items */
318 if (start+n > a->items)
319 a->items = start+n;
320
321 return a;
322 }
323
324
325 Array
DXAllocateArray(Array a,int n)326 DXAllocateArray(Array a, int n)
327 {
328 CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */
329
330 /* second test guarantees something will be allocated even if 0 length */
331 if (n > a->allocated || a->allocated==0) {
332 int bytes = n * a->size;
333 Pointer d;
334 if (bytes > sizeof(a->ldata)) {
335 if (a->data == (Pointer)a->ldata) {
336 d = DXAllocate(bytes);
337 if (!d)
338 return NULL;
339 memcpy(d, a->ldata, sizeof(a->ldata));
340 } else {
341 d = DXReAllocate(a->data, bytes);
342 if (!d)
343 return NULL;
344 }
345 a->data = d;
346 } else
347 a->data = (Pointer)a->ldata;
348 a->allocated = n;
349 }
350 return a;
351 }
352
353
354 Array
DXTrim(Array a)355 DXTrim(Array a)
356 {
357 #if 0 /* EndField() calls this on all arrays regardless of type */
358 CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */
359 #else
360 CHECK(a, CLASS_ARRAY);
361 #endif
362
363 if (a->allocated > a->items) {
364 if (a->data != (Pointer)a->ldata) {
365 Pointer d = DXReAllocate(a->data, a->items*a->size);
366 if (!d) /* realloc shouldn't fail, but just in case ... */
367 DXErrorReturn(ERROR_UNEXPECTED, "re-alloc failed!");
368 a->data = d;
369 }
370 a->allocated = a->items;
371 }
372 return a;
373 }
374
375 /* this might be a useful function to add sometime */
376 Array
DXTrimItems(Array a,int nitems)377 DXTrimItems(Array a, int nitems)
378 {
379 CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */
380
381 /* reset the item count only if smaller,
382 * and release any extra space in either case.
383 */
384 if (a->items > nitems)
385 a->items = nitems;
386
387 return DXTrim(a);
388 }
389
390 Pointer
DXGetArrayData(Array a)391 DXGetArrayData(Array a)
392 {
393 return _dxfGetArrayData(a);
394 }
395
396 ArrayHandle
DXCreateArrayHandle(Array array)397 DXCreateArrayHandle(Array array)
398 {
399 ArrayHandle handle = NULL;
400 Array *terms = NULL;
401
402 handle = (ArrayHandle)DXAllocateZero(sizeof(struct arrayHandle));
403 if (! handle)
404 goto error;
405
406 handle->class = DXGetArrayClass(array);
407 handle->itemSize = DXGetItemSize(array);
408
409 DXGetArrayInfo(array, &handle->nElements,
410 &handle->type, &handle->cat, NULL, NULL);
411
412 handle->nValues = handle->itemSize / DXTypeSize(handle->type);
413
414 if (array->data)
415 {
416 handle->data = array->data;
417 }
418 else if (DXQueryConstantArray(array, NULL, NULL))
419 {
420 handle->cdata = DXAllocate(handle->itemSize);
421 if (! handle->cdata)
422 goto error;
423
424 DXQueryConstantArray(array, NULL, handle->cdata);
425 }
426 else
427 switch(handle->class)
428 {
429 case CLASS_REGULARARRAY:
430 handle->origin = DXAllocate(handle->itemSize);
431 handle->delta = DXAllocate(handle->itemSize);
432 if (! handle->origin || ! handle->delta)
433 goto error;
434 DXGetRegularArrayInfo((RegularArray)array, NULL,
435 handle->origin, handle->delta);
436 break;
437
438 case CLASS_PATHARRAY:
439 break;
440
441 case CLASS_PRODUCTARRAY:
442 {
443 int i;
444
445 DXGetProductArrayInfo((ProductArray)array,
446 &handle->nTerms, NULL);
447
448 terms = (Array *)DXAllocate(handle->nTerms * sizeof(Array));
449
450 handle->scratch1 = (int *)DXAllocate(handle->itemSize);
451 handle->scratch2 = (int *)DXAllocate(handle->itemSize);
452
453 handle->strides = (int *)
454 DXAllocateZero(handle->nTerms * sizeof(int));
455 handle->counts = (int *)
456 DXAllocateZero(handle->nTerms * sizeof(int));
457 handle->scratch = (Pointer *)
458 DXAllocateZero(handle->nTerms * sizeof(Pointer));
459 handle->handles = (ArrayHandle *)
460 DXAllocateZero(handle->nTerms * sizeof(ArrayHandle));
461 handle->indices = (int *)
462 DXAllocateZero(handle->nTerms * sizeof(int));
463
464 if (! handle->strides || ! handle->counts ||
465 ! terms || ! handle->indices ||
466 ! handle->scratch1 || ! handle->scratch2 ||
467 ! handle->scratch || ! handle->handles) goto error;
468
469 DXGetProductArrayInfo((ProductArray)array, NULL, terms);
470
471 for (i = 0; i < handle->nTerms; i++)
472 {
473 handle->handles[i] = DXCreateArrayHandle(terms[i]);
474 if (NULL == handle->handles[i])
475 goto error;
476
477 handle->scratch[i]=DXAllocate(DXGetItemSize(terms[i]));
478 if (NULL == handle->scratch)
479 goto error;
480
481 DXGetArrayInfo(terms[i], &handle->counts[i],
482 NULL, NULL, NULL, NULL);
483 }
484
485 DXFree((Pointer)terms);
486
487 handle->strides[handle->nTerms-1] = 1;
488 for (i = handle->nTerms-2; i >= 0; i--)
489 handle->strides[i] =
490 handle->strides[i+1]*handle->counts[i+1];
491
492 }
493 break;
494
495 case CLASS_MESHARRAY:
496 {
497 int i;
498
499 DXGetMeshArrayInfo((MeshArray)array, &handle->nTerms, NULL);
500
501 terms = (Array *)DXAllocate(handle->nTerms * sizeof(Array));
502
503 handle->scratch1 = (int *)DXAllocate(handle->itemSize);
504 handle->scratch2 = (int *)DXAllocate(handle->itemSize);
505
506 handle->strides = (int *)
507 DXAllocateZero(handle->nTerms * sizeof(int));
508 handle->counts = (int *)
509 DXAllocateZero(handle->nTerms * sizeof(int));
510 handle->scratch = (Pointer *)
511 DXAllocateZero(handle->nTerms * sizeof(Pointer));
512 handle->handles = (ArrayHandle *)
513 DXAllocateZero(handle->nTerms * sizeof(ArrayHandle));
514 handle->indices = (int *)
515 DXAllocateZero(handle->nTerms * sizeof(int));
516
517 if (! handle->strides || ! handle->counts || ! terms ||
518 ! handle->scratch1 || ! handle->scratch2 ||
519 ! handle->indices ||
520 ! handle->scratch || ! handle->handles) goto error;
521
522 DXGetMeshArrayInfo((MeshArray)array, NULL, terms);
523
524 for (i = 0; i < handle->nTerms; i++)
525 {
526 handle->handles[i] = DXCreateArrayHandle(terms[i]);
527 if (NULL == handle->handles[i])
528 goto error;
529
530 handle->scratch[i]=DXAllocate(DXGetItemSize(terms[i]));
531 if (NULL == handle->scratch)
532 goto error;
533
534 DXGetArrayInfo(terms[i], &handle->counts[i],
535 NULL, NULL, NULL, NULL);
536 handle->counts[i] += 1;
537 }
538
539 DXFree((Pointer)terms);
540
541 handle->strides[handle->nTerms-1] = 1;
542 for (i = handle->nTerms-2; i >= 0; i--)
543 handle->strides[i] =
544 handle->strides[i+1]*(handle->counts[i+1]-1);
545
546 }
547 break;
548
549 default:
550 handle->data = DXGetArrayData(array);
551 break;
552 }
553
554 return handle;
555
556 error:
557 DXFreeArrayHandle(handle);
558 DXFree((Pointer)terms);
559 return NULL;
560 }
561
562 Error
DXFreeArrayHandle(ArrayHandle handle)563 DXFreeArrayHandle(ArrayHandle handle)
564 {
565 int i;
566
567 if (handle)
568 {
569 for (i = 0; i < handle->nTerms; i++)
570 {
571 DXFreeArrayHandle(handle->handles[i]);
572 DXFree(handle->scratch[i]);
573 }
574
575 DXFree((Pointer)handle->strides);
576 DXFree((Pointer)handle->counts);
577 DXFree((Pointer)handle->handles);
578 DXFree((Pointer)handle->indices);
579 DXFree((Pointer)handle->scratch);
580 DXFree((Pointer)handle->scratch1);
581 DXFree((Pointer)handle->scratch2);
582 DXFree((Pointer)handle->cdata);
583 DXFree((Pointer)handle->origin);
584 DXFree((Pointer)handle->delta);
585 DXFree((Pointer)handle);
586 }
587
588 return OK;
589 }
590
591 #define REGULAR_GETELEMENT(type) \
592 { \
593 type *dst = (type *)scratch; \
594 type *org = (type *)handle->origin; \
595 type *del = (type *)handle->delta; \
596 int i; \
597 for (i = 0; i < handle->nValues; i++) \
598 *dst++ = *org++ + offset*(*del++); \
599 }
600
601 #define MESHARRAY_ADDTERM(type) \
602 { \
603 type *dst = (type *)scratch; \
604 type *right; \
605 int i, j; \
606 \
607 for (i = 1; i < handle->nTerms; i++) \
608 { \
609 right = (type *)DXGetArrayEntry(handle->handles[i], \
610 handle->indices[i], handle->scratch[i]); \
611 for (j = 0; j < handle->nValues; j++) \
612 dst[j] += right[j]; \
613 } \
614 }
615
616 static void
_dxfTermIndices(ArrayHandle handle,int offset,int * indices)617 _dxfTermIndices(ArrayHandle handle, int offset, int *indices)
618 {
619 int i;
620 for (i = 0; i < handle->nTerms-1; i++)
621 {
622 indices[i] = offset / handle->strides[i];
623 offset = offset % handle->strides[i];
624 }
625
626 indices[handle->nTerms-1] = offset;
627 }
628
629 Pointer
DXCalculateArrayEntry(ArrayHandle handle,int offset,Pointer scratch)630 DXCalculateArrayEntry(ArrayHandle handle, int offset, Pointer scratch)
631 {
632 if (handle->data)
633 return (Pointer)(((char *)handle->data) + offset*handle->itemSize);
634 else if (handle->cdata)
635 return handle->cdata;
636 else
637 {
638 switch (handle->class)
639 {
640 case CLASS_REGULARARRAY:
641 switch(handle->type)
642 {
643 case TYPE_DOUBLE: REGULAR_GETELEMENT(double); break;
644 case TYPE_FLOAT: REGULAR_GETELEMENT(float); break;
645 case TYPE_INT: REGULAR_GETELEMENT(int); break;
646 case TYPE_UINT: REGULAR_GETELEMENT(uint); break;
647 case TYPE_SHORT: REGULAR_GETELEMENT(short); break;
648 case TYPE_USHORT: REGULAR_GETELEMENT(ushort); break;
649 case TYPE_BYTE: REGULAR_GETELEMENT(byte); break;
650 case TYPE_UBYTE: REGULAR_GETELEMENT(ubyte); break;
651 case TYPE_HYPER: case TYPE_STRING: break;
652 }
653 break;
654
655 case CLASS_PATHARRAY:
656 ((int *)scratch)[0] = offset;
657 ((int *)scratch)[1] = offset+1;
658 break;
659
660 case CLASS_MESHARRAY:
661 {
662 _dxfTermIndices(handle, offset, handle->indices);
663
664 if (handle->nTerms == 1)
665 {
666 memcpy(scratch, DXGetArrayEntry(handle->handles[0],
667 handle->indices[0], handle->scratch[0]),
668 handle->handles[0]->itemSize);
669 }
670 else
671 {
672 int *left, *right, *dst, *ptr, i, j, k, nItems;
673
674 memcpy(handle->scratch1, DXGetArrayEntry(handle->handles[0],
675 handle->indices[0], handle->scratch[0]),
676 handle->handles[0]->itemSize);
677
678 nItems = handle->handles[0]->nValues;
679 left = handle->scratch1; dst = handle->scratch2;
680 for (i = 1; i < handle->nTerms; i++)
681 {
682 if (i == handle->nTerms-1)
683 dst = (int *)scratch;
684
685 right = (int *)DXGetArrayEntry(handle->handles[i],
686 handle->indices[i], handle->scratch[i]);
687
688 ptr = dst;
689 for (j = 0; j < nItems; j++)
690 {
691 int tmp = left[j] * handle->counts[i];
692
693 for (k = 0; k < handle->handles[i]->nValues; k++)
694 *ptr++ = tmp + right[k];
695 }
696
697 nItems *= handle->handles[i]->nValues;
698
699 ptr = dst;
700 dst = left;
701 left = ptr;
702 }
703 }
704 }
705 break;
706
707 case CLASS_PRODUCTARRAY:
708 {
709 _dxfTermIndices(handle, offset, handle->indices);
710
711 if (handle->nTerms == 1)
712 {
713 memcpy(scratch, DXGetArrayEntry(handle->handles[0],
714 handle->indices[0], handle->scratch[0]),
715 handle->handles[0]->itemSize);
716 }
717 else
718 {
719 memcpy(scratch, DXGetArrayEntry(handle->handles[0],
720 handle->indices[0], handle->scratch[0]),
721 handle->handles[0]->itemSize);
722
723 switch(handle->type)
724 {
725 case TYPE_DOUBLE: MESHARRAY_ADDTERM(double); break;
726 case TYPE_FLOAT: MESHARRAY_ADDTERM(float); break;
727 case TYPE_INT: MESHARRAY_ADDTERM(int); break;
728 case TYPE_UINT: MESHARRAY_ADDTERM(uint); break;
729 case TYPE_SHORT: MESHARRAY_ADDTERM(short); break;
730 case TYPE_USHORT: MESHARRAY_ADDTERM(ushort); break;
731 case TYPE_BYTE: MESHARRAY_ADDTERM(byte); break;
732 case TYPE_UBYTE: MESHARRAY_ADDTERM(ubyte); break;
733 case TYPE_HYPER: case TYPE_STRING: break;
734 }
735 }
736 }
737 break;
738 default: /* All other TYPEs and CLASSes */
739 break;
740 }
741
742 }
743 return scratch;
744
745 }
746
747
748 /* make string arrays */
749 Array
DXMakeStringList(int n,char * s,...)750 DXMakeStringList(int n, char *s, ...)
751 {
752 int i;
753 char **c;
754 va_list arg;
755 Array a;
756
757 if (n == 0)
758 return NULL;
759
760 if (n < 0) {
761 DXSetError(ERROR_BAD_PARAMETER, "#10020", "stringlist count");
762 return NULL;
763 }
764
765 c = (char **)DXAllocate(n * sizeof(char *));
766 if (!c)
767 return NULL;
768
769 c[0] = s;
770
771 /* collect args */
772 va_start(arg,s);
773 for (i=1; i<n; i++)
774 c[i] = va_arg(arg, char *);
775 va_end(arg);
776
777 /* call V version */
778 a = DXMakeStringListV(n, c);
779
780 DXFree(c);
781 return a;
782 }
783
784 /* count plus string list */
785 Array
DXMakeStringListV(int n,char ** s)786 DXMakeStringListV(int n, char **s)
787 {
788 Array a;
789 int i;
790 int count, l, maxlen = 0;
791 char *p;
792
793 if (n == 0 || !s)
794 return NULL;
795
796 if (n < 0) {
797 DXSetError(ERROR_BAD_PARAMETER, "#10020", "stringlist count");
798 return NULL;
799 }
800
801 for (count=0; count < n; count++) {
802 if (!s[count])
803 continue;
804
805 if ((l=strlen(s[count])) > maxlen)
806 maxlen = l;
807 }
808
809 a = DXNewArray(TYPE_STRING, CATEGORY_REAL, 1, maxlen+1);
810 if (!a)
811 return NULL;
812
813 if (!DXAddArrayData(a, 0, n, NULL))
814 goto error;
815
816 p = (char *)DXGetArrayData(a);
817 if (!p)
818 goto error;
819
820 for (i=0; i<n; i++, p += maxlen+1)
821 s[i] ? strncpy(p, s[i], maxlen+1) : memset(p, '\0', maxlen+1);
822
823 return a;
824
825 error:
826 DXDelete((Object)a);
827 return NULL;
828 }
829
830 static Array
packit(int n,Type t,Category c,int rank,int * shape,Pointer p)831 packit(int n, Type t, Category c, int rank, int *shape, Pointer p)
832 {
833 Array a = NULL;
834
835 a = DXNewArrayV(t, c, rank, shape);
836 if (!a)
837 return NULL;
838
839 if (!DXAddArrayData(a, 0, n, p)) {
840 DXDelete((Object)a);
841 return NULL;
842 }
843
844 return a;
845 }
846
DXMakeInteger(int n)847 Array DXMakeInteger(int n)
848 {
849 return packit(1, TYPE_INT, CATEGORY_REAL, 0, NULL, (Pointer)&n);
850 }
851
DXMakeFloat(float f)852 Array DXMakeFloat(float f)
853 {
854 return packit(1, TYPE_FLOAT, CATEGORY_REAL, 0, NULL, (Pointer)&f);
855 }
856