Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/MD_package/MDUtility.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 117 - (show annotations) (download) (as text)
Sun Oct 1 03:33:45 2017 UTC (6 years, 6 months ago) by toshinagata1964
File MIME type: text/x-csrc
File size: 22166 byte(s)
Sizes of the integer types are reconsidered.
1 /*
2 MDUtility.c
3 Created by Toshi Nagata, 2000.11.24.
4
5 Copyright (c) 2000-2016 Toshi Nagata. All rights reserved.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 */
16
17 #include "MDHeaders.h"
18
19 #include <stdarg.h> /* for va_start/va_arg/va_end macros */
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <malloc/malloc.h> /* for malloc_size() */
25
26 #ifdef __MWERKS__
27 #pragma mark ====== Stream functions ======
28 #endif
29
30 /* --------------------------------------
31 ï½¥ MDReadStreamFormat
32 -------------------------------------- */
33 int32_t
34 MDReadStreamFormat(STREAM stream, const char *format, ...)
35 {
36 va_list ap;
37 char *p = (char *)format;
38 unsigned char c, star, s[4];
39 int32_t count, n, numResult;
40 size_t len;
41 char *cp;
42 short *sp;
43 int32_t *lp;
44
45 va_start(ap, format);
46 numResult = 0;
47 while (*p != 0) {
48 while (isspace(*p)) p++;
49 c = *p++;
50 if (c == 0)
51 break;
52 while (isspace(*p)) p++;
53 star = 0;
54 if (*p == '*') {
55 star = '*';
56 count = 1;
57 p++;
58 } else if (*p != 0) {
59 count = (int)strtol(p, &p, 0);
60 if (count == 0)
61 count = 1;
62 } else count = 1;
63 for ( ; count > 0; count--) {
64 switch (c) {
65 case 'a': /* ASCII string, null padded */
66 case 'A': /* ASCII string, space padded */
67 /* Does not care if encountered null bytes from stream */
68 cp = va_arg(ap, char *);
69 if (star)
70 count = va_arg(ap, int32_t);
71 len = FREAD_(cp, count, stream);
72 if (len < count)
73 memset(cp + n, (c == 'a' ? 0 : ' '), count - n);
74 cp[count] = 0; /* terminate */
75 count = 1; /* one time only */
76 break;
77 case 'c': /* signed char */
78 case 'C': /* unsigned char */
79 cp = va_arg(ap, char *);
80 n = GETC(stream);
81 if (n == EOF)
82 goto end;
83 *cp = n;
84 break;
85 case 'n': /* signed short, big-endian */
86 sp = va_arg(ap, short *);
87 len = FREAD_(s, 2, stream);
88 if (len < 2)
89 goto end;
90 *sp = (s[0] << 8) + s[1];
91 break;
92 case 'N': /* signed int32_t, big-endian */
93 lp = va_arg(ap, int32_t *);
94 len = FREAD_(s, 4, stream);
95 if (len < 4)
96 goto end;
97 *lp = (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3];
98 break;
99 case 'w': /* BER compressed integer --- 'variable length number' in SMF */
100 {
101 int32_t val = 0;
102 lp = va_arg(ap, int32_t *);
103 while ((n = GETC(stream)) != EOF) {
104 val = (val << 7) + (n & 0x7f);
105 if ((n & 0x80) == 0)
106 break;
107 }
108 *lp = val;
109 if (n == EOF)
110 goto end;
111 break;
112 }
113 default:
114 cp = va_arg(ap, char *); /* skip one argument */
115 break;
116 } /* end switch */
117 numResult++;
118 } /* end loop */
119 }
120 end:
121 va_end(ap);
122 return numResult;
123 }
124
125 /* --------------------------------------
126 ï½¥ MDReadStreamFormat
127 -------------------------------------- */
128 int32_t
129 MDWriteStreamFormat(STREAM stream, const char *format, ...)
130 {
131 va_list ap;
132 char *p = (char *)format;
133 unsigned char c, star, s[4];
134 int32_t count, n, numResult;
135 int i;
136 char *cp;
137
138 va_start(ap, format);
139 numResult = 0;
140 while (*p != 0) {
141 while (isspace(*p)) p++;
142 c = *p++;
143 if (c == 0)
144 break;
145 while (isspace(*p)) p++;
146 star = 0;
147 if (*p == '*') {
148 star = '*';
149 count = 1;
150 p++;
151 } else if (*p != 0) {
152 count = (int)strtol(p, &p, 0);
153 if (count == 0)
154 count = 1;
155 } else count = 1;
156 for ( ; count > 0; count--) {
157 switch (c) {
158 case 'a': /* ASCII string, null padded */
159 case 'A': /* ASCII string, space padded */
160 cp = va_arg(ap, char *);
161 if (star)
162 count = va_arg(ap, int32_t);
163 n = (int)FWRITE_(cp, count, stream);
164 count = 1; /* one time only */
165 break;
166 case 'c': /* signed char */
167 case 'C': /* unsigned char */
168 i = va_arg(ap, int);
169 n = PUTC(i, stream);
170 if (n == EOF)
171 goto end;
172 break;
173 case 'n': /* signed short, big-endian */
174 i = va_arg(ap, int);
175 s[0] = (i >> 8);
176 s[1] = i;
177 n = (int)FWRITE_(s, 2, stream);
178 if (n < 2)
179 goto end;
180 break;
181 case 'N': /* signed int32_t, big-endian */
182 n = va_arg(ap, int32_t);
183 s[0] = (n >> 24);
184 s[1] = (n >> 16);
185 s[2] = (n >> 8);
186 s[3] = n;
187 n = (int)FWRITE_(s, 4, stream);
188 if (n < 4)
189 goto end;
190 break;
191 case 'w': /* BER compressed integer --- 'variable length number' in SMF */
192 {
193 uint32_t un;
194 un = va_arg(ap, uint32_t);
195 s[3] = (un & 0x7f);
196 i = 3;
197 while (i > 0) {
198 un >>= 7;
199 if (un == 0)
200 break;
201 s[--i] = ((un & 0x7f) | 0x80);
202 }
203 n = (int)FWRITE_(s + i, 4 - i, stream);
204 if (n < 4 - i)
205 goto end;
206 break;
207 }
208 default:
209 cp = va_arg(ap, char *); /* skip one argument */
210 break;
211 } /* end switch */
212 numResult++;
213 } /* end loop */
214 }
215 end:
216 va_end(ap);
217 return numResult;
218 }
219
220 #pragma mark ====== File Stream ======
221
222 static int
223 MDFileStreamGetc(STREAM stream)
224 {
225 return getc(((file_stream_record *)stream)->file);
226 }
227
228 static int
229 MDFileStreamPutc(STREAM stream, int c)
230 {
231 return putc(c, ((file_stream_record *)stream)->file);
232 }
233
234 static size_t
235 MDFileStreamFread(STREAM stream, void *ptr, size_t size)
236 {
237 return fread(ptr, 1, size, ((file_stream_record *)stream)->file);
238 }
239
240 static size_t
241 MDFileStreamFwrite(STREAM stream, const void *ptr, size_t size)
242 {
243 return fwrite(ptr, 1, size, ((file_stream_record *)stream)->file);
244 }
245
246 static int
247 MDFileStreamFseek(STREAM stream, off_t offset, int whence)
248 {
249 return fseeko(((file_stream_record *)stream)->file, offset, whence);
250 }
251
252 static off_t
253 MDFileStreamFtell(STREAM stream)
254 {
255 return ftello(((file_stream_record *)stream)->file);
256 }
257
258 static int
259 MDFileStreamFclose(STREAM stream)
260 {
261 int retval = fclose(((file_stream_record *)stream)->file);
262 free(stream);
263 return retval;
264 }
265
266 /* --------------------------------------
267 ï½¥ MDStreamOpenFile
268 -------------------------------------- */
269 STREAM
270 MDStreamOpenFile(const char *fname, const char *mode)
271 {
272 STREAM stream = (STREAM)malloc(sizeof(file_stream_record));
273 if (stream == NULL)
274 return NULL;
275 stream->getc = MDFileStreamGetc;
276 stream->putc = MDFileStreamPutc;
277 stream->fread = MDFileStreamFread;
278 stream->fwrite = MDFileStreamFwrite;
279 stream->fseek = MDFileStreamFseek;
280 stream->ftell = MDFileStreamFtell;
281 stream->fclose = MDFileStreamFclose;
282 ((file_stream_record *)stream)->file = fopen(fname, mode);
283 if (((file_stream_record *)stream)->file == NULL) {
284 free(stream);
285 return NULL;
286 }
287 return stream;
288 }
289
290 #pragma mark ====== Data Stream ======
291
292 static int
293 MDDataStreamGetc(STREAM stream)
294 {
295 data_stream_record *dp = (data_stream_record *)stream;
296 if (dp->ptr == NULL || dp->offset >= dp->size)
297 return -1;
298 return dp->ptr[dp->offset++];
299 }
300
301 static void *
302 MDDataStreamReallocate(data_stream_record *dp, size_t size_to_extend)
303 {
304 size_t new_size;
305 void *p;
306 if (dp->ptr == NULL) {
307 new_size = (size_to_extend / MDDATASTREAM_PAGESIZE + 1) * MDDATASTREAM_PAGESIZE;
308 p = malloc(new_size);
309 if (p != NULL) {
310 dp->ptr = p;
311 dp->bufsize = new_size;
312 dp->offset = dp->size = 0;
313 return p;
314 } else return NULL;
315 } else {
316 new_size = (size_t)((dp->offset + size_to_extend) / MDDATASTREAM_PAGESIZE + 1) * MDDATASTREAM_PAGESIZE;
317 if (new_size > dp->bufsize) {
318 p = realloc(dp->ptr, new_size);
319 if (p != NULL) {
320 dp->ptr = p;
321 dp->bufsize = new_size;
322 return p;
323 } else return NULL;
324 } else return dp->ptr;
325 }
326 }
327
328 static int
329 MDDataStreamPutc(STREAM stream, int c)
330 {
331 data_stream_record *dp = (data_stream_record *)stream;
332 if (dp->ptr == NULL || dp->offset >= dp->bufsize) {
333 if (MDDataStreamReallocate(dp, 1) == NULL)
334 return -1;
335 }
336 dp->ptr[dp->offset++] = c;
337 if (dp->offset > dp->size)
338 dp->size = (size_t)dp->offset;
339 return c;
340 }
341
342 static size_t
343 MDDataStreamFread(STREAM stream, void *ptr, size_t size)
344 {
345 data_stream_record *dp = (data_stream_record *)stream;
346 if (dp->ptr == NULL)
347 return -1;
348 if (dp->offset >= dp->size)
349 return -1;
350 if (dp->offset + size > dp->size)
351 size = dp->size - (size_t)dp->offset;
352 memmove(ptr, dp->ptr + dp->offset, size);
353 dp->offset += size;
354 return size;
355 }
356
357 static size_t
358 MDDataStreamFwrite(STREAM stream, const void *ptr, size_t size)
359 {
360 data_stream_record *dp = (data_stream_record *)stream;
361 if (dp->ptr == NULL || dp->offset + size >= dp->bufsize) {
362 if (MDDataStreamReallocate(dp, size) == NULL)
363 return -1;
364 }
365 memmove(dp->ptr + dp->offset, ptr, size);
366 dp->offset += size;
367 if (dp->offset > dp->size)
368 dp->size = (size_t)dp->offset;
369 return size;
370 }
371
372 static int
373 MDDataStreamFseek(STREAM stream, off_t offset, int whence)
374 {
375 data_stream_record *dp = (data_stream_record *)stream;
376 off_t target;
377 if (whence == SEEK_SET)
378 target = offset;
379 else if (whence == SEEK_CUR)
380 target = dp->offset + offset;
381 else if (whence == SEEK_END)
382 target = dp->size + offset;
383 else return -1;
384 if (target < 0 || target > dp->size)
385 return -1;
386 dp->offset = target;
387 return 0;
388 }
389
390 static off_t
391 MDDataStreamFtell(STREAM stream)
392 {
393 data_stream_record *dp = (data_stream_record *)stream;
394 return dp->offset;
395 }
396
397 static int
398 MDDataStreamFclose(STREAM stream)
399 {
400 /* The data pointer is not freed */
401 free(stream);
402 return 0;
403 }
404
405 /* --------------------------------------
406 ï½¥ MDStreamOpenData
407 -------------------------------------- */
408 STREAM
409 MDStreamOpenData(void *ptr, size_t size)
410 {
411 data_stream_record *dp = (data_stream_record *)calloc(sizeof(data_stream_record), 1);
412 if (dp == NULL)
413 return NULL;
414 dp->base.getc = MDDataStreamGetc;
415 dp->base.putc = MDDataStreamPutc;
416 dp->base.fread = MDDataStreamFread;
417 dp->base.fwrite = MDDataStreamFwrite;
418 dp->base.fseek = MDDataStreamFseek;
419 dp->base.ftell = MDDataStreamFtell;
420 dp->base.fclose = MDDataStreamFclose;
421 dp->ptr = ptr;
422 dp->size = size;
423 if (ptr == NULL)
424 dp->bufsize = 0;
425 else
426 dp->bufsize = size;
427 return (STREAM)dp;
428 }
429
430 /* --------------------------------------
431 ï½¥ MDStreamGetData
432 -------------------------------------- */
433 int
434 MDStreamGetData(STREAM stream, void **ptr, size_t *size)
435 {
436 if (stream == NULL || stream->getc != MDDataStreamGetc)
437 return -1;
438 if (ptr != NULL)
439 *ptr = ((data_stream_record *)stream)->ptr;
440 if (size != NULL)
441 *size = ((data_stream_record *)stream)->size;
442 return 0;
443 }
444
445 #ifdef __MWERKS__
446 #pragma mark ====== Debug print ======
447 #endif
448
449 #if DEBUG
450
451 int gMDVerbose = 0;
452
453 int
454 _dprintf(const char *fname, int lineno, int level, const char *fmt, ...)
455 {
456 int n = 0;
457 va_list ap;
458 va_start(ap, fmt);
459 fprintf(stderr, "%d %s[%d]: ", level, (fname != NULL ? fname : ""), lineno);
460 n = vfprintf(stderr, fmt, ap);
461 va_end(ap);
462 return n;
463 }
464 #endif
465
466 #ifdef __MWERKS__
467 #pragma mark ====== MDArray implementations ======
468 #endif
469
470 /* --------------------------------------
471 ï½¥ MDArrayCallDestructor
472 -------------------------------------- */
473 static void
474 MDArrayCallDestructor(MDArray *arrayRef, int32_t startIndex, int32_t endIndex)
475 {
476 int32_t i;
477 if (arrayRef == NULL || arrayRef->destructor == NULL)
478 return;
479 if (startIndex < 0)
480 startIndex = 0;
481 if (endIndex >= arrayRef->num)
482 endIndex = arrayRef->num - 1;
483 for (i = startIndex; i <= endIndex; i++) {
484 (*(arrayRef->destructor))((char *)(arrayRef->data) + i * arrayRef->elemSize);
485 }
486 memset((char *)(arrayRef->data) + startIndex * arrayRef->elemSize, 0, arrayRef->elemSize * (endIndex - startIndex + 1));
487 }
488
489 /* --------------------------------------
490 ï½¥ MDArrayAdjustStorage
491 -------------------------------------- */
492 static MDStatus
493 MDArrayAdjustStorage(MDArray *arrayRef, int32_t inLength)
494 {
495 int32_t theNewSize;
496 int32_t page = arrayRef->pageSize;
497
498 theNewSize = ((inLength + page - 1) / page) * page;
499 if (theNewSize == arrayRef->maxIndex)
500 return kMDNoError;
501
502 if (arrayRef->maxIndex == 0 && theNewSize != 0) {
503 arrayRef->data = malloc(theNewSize * arrayRef->elemSize);
504 if (arrayRef->data == NULL)
505 return kMDErrorOutOfMemory;
506 } else if (arrayRef->maxIndex != 0 && theNewSize == 0) {
507 MDArrayCallDestructor(arrayRef, 0, arrayRef->maxIndex - 1);
508 free(arrayRef->data);
509 arrayRef->data = NULL;
510 } else {
511 void *ptr;
512 if (theNewSize < arrayRef->maxIndex)
513 MDArrayCallDestructor(arrayRef, theNewSize, arrayRef->maxIndex - 1);
514 ptr = realloc(arrayRef->data, theNewSize * arrayRef->elemSize);
515 if (ptr == NULL)
516 return kMDErrorOutOfMemory;
517 arrayRef->data = ptr;
518 if (theNewSize > arrayRef->maxIndex) {
519 memset((char *)ptr + arrayRef->maxIndex * arrayRef->elemSize, 0,
520 (theNewSize - arrayRef->maxIndex) * arrayRef->elemSize);
521 }
522 }
523 arrayRef->maxIndex = theNewSize;
524 return kMDNoError;
525 }
526
527 /* --------------------------------------
528 ï½¥ MDArrayNew
529 -------------------------------------- */
530 MDArray *
531 MDArrayNew(int32_t elementSize)
532 {
533 return MDArrayNewWithPageSize(elementSize, kMDArrayDefaultPageSize);
534 }
535
536 /* --------------------------------------
537 ï½¥ MDArrayNewWithPageSize
538 -------------------------------------- */
539 MDArray *
540 MDArrayNewWithPageSize(int32_t elementSize, int32_t pageSize)
541 {
542 MDArray *arrayRef = (MDArray *)malloc(sizeof(*arrayRef));
543 if (arrayRef == NULL)
544 return NULL; /* out of memory */
545 arrayRef->data = NULL;
546 arrayRef->num = arrayRef->maxIndex = 0;
547 arrayRef->elemSize = elementSize;
548 arrayRef->pageSize = pageSize;
549 arrayRef->refCount = 1;
550 arrayRef->allocated = 1;
551 arrayRef->destructor = NULL;
552 return arrayRef;
553 }
554
555 /* --------------------------------------
556 ï½¥ MDArrayNewWithDestructor
557 -------------------------------------- */
558 MDArray *
559 MDArrayNewWithDestructor(int32_t elementSize, void (*destructor)(void *))
560 {
561 MDArray *arrayRef = MDArrayNew(elementSize);
562 if (arrayRef != NULL) {
563 arrayRef->destructor = destructor;
564 }
565 return arrayRef;
566 }
567
568 /* --------------------------------------
569 ï½¥ MDArrayInit
570 -------------------------------------- */
571 MDArray *
572 MDArrayInit(MDArray *arrayRef, int32_t elementSize)
573 {
574 return MDArrayInitWithPageSize(arrayRef, elementSize, kMDArrayDefaultPageSize);
575 }
576
577 /* --------------------------------------
578 ï½¥ MDArrayInitWithPageSize
579 -------------------------------------- */
580 MDArray *
581 MDArrayInitWithPageSize(MDArray *arrayRef, int32_t elementSize, int32_t pageSize)
582 {
583 arrayRef->data = NULL;
584 arrayRef->num = arrayRef->maxIndex = 0;
585 arrayRef->elemSize = elementSize;
586 arrayRef->pageSize = pageSize;
587 arrayRef->refCount = 1;
588 arrayRef->allocated = 0;
589 arrayRef->destructor = NULL;
590 return arrayRef;
591 }
592
593 /* --------------------------------------
594 ï½¥ MDArrayRetain
595 -------------------------------------- */
596 void
597 MDArrayRetain(MDArray *arrayRef)
598 {
599 arrayRef->refCount++;
600 }
601
602 /* --------------------------------------
603 ï½¥ MDArrayRelease
604 -------------------------------------- */
605 void
606 MDArrayRelease(MDArray *arrayRef)
607 {
608 if (--arrayRef->refCount == 0) {
609 MDArrayEmpty(arrayRef);
610 if (arrayRef->allocated)
611 free(arrayRef);
612 }
613 }
614
615 /* --------------------------------------
616 ï½¥ MDArrayEmpty
617 -------------------------------------- */
618 void
619 MDArrayEmpty(MDArray *arrayRef)
620 {
621 if (arrayRef->data != NULL) {
622 MDArrayCallDestructor(arrayRef, 0, arrayRef->num - 1);
623 free(arrayRef->data);
624 arrayRef->data = NULL;
625 }
626 arrayRef->num = arrayRef->maxIndex = 0;
627 }
628
629 /* --------------------------------------
630 ï½¥ MDArrayCount
631 -------------------------------------- */
632 int32_t
633 MDArrayCount(const MDArray *arrayRef)
634 {
635 return arrayRef->num;
636 }
637
638 MDStatus
639 MDArraySetCount(MDArray *arrayRef, int32_t inCount)
640 {
641 MDStatus result;
642 if (inCount < 0)
643 return kMDErrorBadArrayIndex;
644 if (inCount == arrayRef->num)
645 return kMDNoError;
646 result = MDArrayAdjustStorage(arrayRef, inCount);
647 if (result != kMDNoError)
648 return result;
649 if (arrayRef->num < inCount) {
650 /* Clear the elongated part */
651 memset((char *)arrayRef->data + arrayRef->num * inCount, 0, (inCount - arrayRef->num) * arrayRef->elemSize);
652 } else {
653 /* Clear the truncated part (not necessary, but may be useful to avoid nasty bugs) */
654 if (arrayRef->maxIndex > inCount)
655 memset((char *)arrayRef->data + inCount * arrayRef->elemSize, 0, (arrayRef->maxIndex - inCount) * arrayRef->elemSize);
656 }
657 arrayRef->num = inCount;
658 return kMDNoError;
659 }
660
661 /* --------------------------------------
662 ï½¥ MDArrayInsert
663 -------------------------------------- */
664 MDStatus
665 MDArrayInsert(MDArray *arrayRef, int32_t inIndex, int32_t inLength, const void *inData)
666 {
667 MDStatus result;
668 int32_t moveAmount;
669
670 if (inIndex < 0 || inIndex > arrayRef->num)
671 return kMDErrorBadArrayIndex;
672
673 result = MDArrayAdjustStorage(arrayRef, arrayRef->num + inLength);
674 if (result != kMDNoError)
675 return result; /* out of memory */
676
677 moveAmount = (arrayRef->num - inIndex) * arrayRef->elemSize;
678 if (moveAmount > 0) {
679 memmove(
680 (char *)arrayRef->data + (inIndex + inLength) * arrayRef->elemSize,
681 (char *)arrayRef->data + inIndex * arrayRef->elemSize,
682 moveAmount);
683 }
684
685 memmove(
686 (char *)arrayRef->data + inIndex * arrayRef->elemSize,
687 inData,
688 inLength * arrayRef->elemSize);
689
690 arrayRef->num += inLength;
691 return kMDNoError;
692 }
693
694 /* --------------------------------------
695 ï½¥ MDArrayDelete
696 -------------------------------------- */
697 MDStatus
698 MDArrayDelete(MDArray *arrayRef, int32_t inIndex, int32_t inLength)
699 {
700 int32_t moveAmount;
701
702 if (inIndex + inLength > arrayRef->num)
703 inLength = arrayRef->num - inIndex;
704 if (inIndex < 0 || inIndex >= arrayRef->num || inLength < 0)
705 return kMDErrorBadArrayIndex;
706
707 moveAmount = (arrayRef->num - (inIndex + inLength));
708 if (moveAmount > 0) {
709 MDArrayCallDestructor(arrayRef, inIndex, inIndex + inLength - 1);
710 memmove(
711 (char *)arrayRef->data + inIndex * arrayRef->elemSize,
712 (char *)arrayRef->data + (inIndex + inLength) * arrayRef->elemSize,
713 moveAmount * arrayRef->elemSize);
714 }
715 arrayRef->num -= inLength;
716 return kMDNoError;
717 }
718
719 /* --------------------------------------
720 ï½¥ MDArrayReplace
721 -------------------------------------- */
722 MDStatus
723 MDArrayReplace(MDArray *arrayRef, int32_t inIndex, int32_t inLength, const void *inData)
724 {
725 MDStatus result;
726 MDArrayCallDestructor(arrayRef, inIndex, inIndex + inLength - 1);
727 if (inIndex + inLength > arrayRef->maxIndex) {
728 result = MDArrayAdjustStorage(arrayRef, inIndex + inLength);
729 if (result != 0)
730 return result; /* out of memory */
731 }
732 memmove(
733 (char *)arrayRef->data + inIndex * arrayRef->elemSize,
734 inData,
735 inLength * arrayRef->elemSize);
736 if (inIndex + inLength > arrayRef->num)
737 arrayRef->num = inIndex + inLength;
738 return kMDNoError;
739 }
740
741 /* --------------------------------------
742 ï½¥ MDArrayFetch
743 -------------------------------------- */
744 int32_t
745 MDArrayFetch(const MDArray *arrayRef, int32_t inIndex, int32_t inLength, void *outData)
746 {
747 if (inIndex + inLength > arrayRef->num)
748 inLength = arrayRef->num - inIndex;
749 if (inIndex < 0 || inIndex >= arrayRef->num || inLength <= 0)
750 return 0;
751 memmove(
752 outData,
753 (char *)arrayRef->data + inIndex * arrayRef->elemSize,
754 inLength * arrayRef->elemSize);
755 return inLength;
756 }
757
758 /* --------------------------------------
759 ï½¥ MDArrayFetchPtr
760 -------------------------------------- */
761 void *
762 MDArrayFetchPtr(const MDArray *arrayRef, int32_t inIndex)
763 {
764 if (inIndex < 0 || inIndex >= arrayRef->num)
765 return NULL;
766 return (char *)arrayRef->data + inIndex * arrayRef->elemSize;
767 }
768
769 #pragma mark ====== Simpler Array Implementation ======
770
771 /* Assign a value to an array. An array is represented by two fields; count and base,
772 * where base is a pointer to an array and count is the number of items.
773 * The memory block of the array is allocated by 8*item_size. If the index exceeds
774 * that limit, then a new memory block is allocated. */
775 void *
776 AssignArray(void *base, int *count, int item_size, int idx, const void *value)
777 {
778 void **bp = (void **)base;
779 if (*count == 0 || idx / 8 > (*count - 1) / 8) {
780 int new_size = (idx / 8 + 1) * 8;
781 if (*bp == NULL)
782 *bp = calloc(item_size, new_size);
783 else
784 *bp = realloc(*bp, new_size * item_size);
785 if (*bp == NULL)
786 return NULL;
787 memset((char *)*bp + *count * item_size, 0, (new_size - *count) * item_size);
788 }
789 if (idx >= *count)
790 *count = idx + 1;
791 if (value != NULL)
792 memcpy((char *)*bp + idx * item_size, value, item_size);
793 return (char *)*bp + idx * item_size;
794 }
795
796 /* Allocate a new array. This works consistently with AssignArray().
797 * Don't mix calloc()/malloc() with AssignArray(); that causes disasters!
798 * (free() is OK though). */
799 void *
800 NewArray(void *base, int *count, int item_size, int nitems)
801 {
802 void **bp = (void *)base;
803 *bp = NULL;
804 *count = 0;
805 if (nitems > 0)
806 return AssignArray(base, count, item_size, nitems - 1, NULL);
807 else return NULL;
808 }
809
810 /* Insert items to an array. */
811 void *
812 InsertArray(void *base, int *count, int item_size, int idx, int nitems, const void *value)
813 {
814 void **bp = (void *)base;
815 void *p;
816 int ocount = *count;
817 if (nitems <= 0)
818 return NULL;
819 /* Allocate storage */
820 p = AssignArray(base, count, item_size, *count + nitems - 1, NULL);
821 if (p == NULL)
822 return NULL;
823 /* Move items if necessary */
824 if (idx < ocount)
825 memmove((char *)*bp + (idx + nitems) * item_size, (char *)*bp + idx * item_size, (ocount - idx) * item_size);
826 /* Copy items */
827 if (value != NULL)
828 memmove((char *)*bp + idx * item_size, value, nitems * item_size);
829 else
830 memset((char *)*bp + idx * item_size, 0, nitems * item_size);
831 return (char *)*bp + idx * item_size;
832 }
833
834 void *
835 DeleteArray(void *base, int *count, int item_size, int idx, int nitems, void *outValue)
836 {
837 void **bp = (void *)base;
838 if (nitems <= 0 || idx < 0 || idx >= *count)
839 return NULL;
840 if (nitems > *count - idx)
841 nitems = *count - idx;
842 /* Copy items */
843 if (outValue != NULL)
844 memmove(outValue, (char *)*bp + idx * item_size, nitems * item_size);
845 /* Move items */
846 if (idx + nitems < *count)
847 memmove((char *)*bp + idx * item_size, (char *)*bp + (idx + nitems) * item_size, (*count - idx - nitems) * item_size);
848 *count -= nitems;
849 if (*count == 0) {
850 free(*bp);
851 *bp = NULL;
852 }
853 return NULL;
854 }
855

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26