1 /* ----------------------------- MNI Header -----------------------------------
2 @NAME : group.c
3 @DESCRIPTION: Routines for doing acr_nema group operations.
4 @METHOD :
5 @GLOBALS :
6 @CREATED : November 10, 1993 (Peter Neelin)
7 @MODIFIED :
8 * $Log: group.c,v $
9 * Revision 6.12 2008-08-12 05:00:22 rotor
10 * * large number of changes from Claude (64 bit and updates)
11 *
12 * Revision 6.11 2006/04/09 15:29:43 bert
13 * Add acr_insert_double()
14 *
15 * Revision 6.10 2005/05/09 15:34:46 bert
16 * For acr_find_{short,int,long,double}, treat a zero-length element as if it were absent, and return the default value.
17 *
18 * Revision 6.9 2005/03/11 22:05:29 bert
19 * Implement _acr_name_proc to allow printing of field names in dump_acr_nema
20 *
21 * Revision 6.8 2005/03/04 17:09:11 bert
22 * Change several functions to return Acr_Status instead of void; lose public and private; Make insert_element() check the return value of acr_get_element_total_length()
23 *
24 * Revision 6.7 2004/10/29 13:08:42 rotor
25 * * rewrote Makefile with no dependency on a minc distribution
26 * * removed all references to the abominable minc_def.h
27 * * I should autoconf this really, but this is old code that
28 * is now replaced by Jon Harlaps PERL version..
29 *
30 * Revision 6.6 2002/12/08 22:31:34 neelin
31 * When a last fragment is received, the dicom watchpoint is only updated when the next read happens, so the peek ahead will fail after the watchpoint test in acr_input_group_with_max.
32 *
33 * Revision 6.5 2001/11/08 14:17:05 neelin
34 * Added acr_test_dicom_file to allow reading of DICOM part 10 format
35 * files. This function also calls acr_test_byte_order to set up the stream
36 * properly and can be used as a direct replacement for that function.
37 * This set of changes does NOT include the ability to write part 10 files.
38 *
39 * Revision 6.4 2000/05/01 17:18:07 neelin
40 * Modifications tohandle end-of-input properly, both on first group
41 * read, and when ignoring protocol errors.
42 *
43 * Revision 6.3 2000/04/28 15:03:11 neelin
44 * Added support for ignoring non-fatal protocol errors (cases where redundant
45 * information is inconsistent). In particular, it is possible to ignore
46 * differences between the group length element and the true group length.
47 *
48 * Revision 6.2 1999/10/29 17:51:53 neelin
49 * Fixed Log keyword
50 *
51 * Revision 6.1 1998/11/06 19:41:06 neelin
52 * Added functions acr_group_steal_element and acr_find_group.
53 *
54 * Revision 6.0 1997/09/12 13:23:59 neelin
55 * Release of minc version 0.6
56 *
57 * Revision 5.0 1997/08/21 13:25:00 neelin
58 * Release of minc version 0.5
59 *
60 * Revision 4.2 1997/08/21 13:24:55 neelin
61 * Pre-release
62 *
63 * Revision 4.1 1997/06/17 23:49:08 neelin
64 * Added routines for inserting elements into a group list.
65 *
66 * Revision 4.0 1997/05/07 20:01:23 neelin
67 * Release of minc version 0.4
68 *
69 * Revision 3.1 1997/04/21 20:21:09 neelin
70 * Updated the library to handle dicom messages.
71 *
72 * Revision 3.0 1995/05/15 19:32:12 neelin
73 * Release of minc version 0.3
74 *
75 * Revision 2.2 1995/02/08 21:16:06 neelin
76 * Changes to make irix 5 lint happy.
77 *
78 * Revision 2.1 1995/01/04 08:10:16 neelin
79 * Improved string printing in dump function (longer strings and replace
80 * carriage returns, linefeeds and formfeeds by spaces).
81 *
82 * Revision 2.0 94/09/28 10:36:16 neelin
83 * Release of minc version 0.2
84 *
85 * Revision 1.11 94/09/28 10:35:45 neelin
86 * Pre-release
87 *
88 * Revision 1.10 94/04/07 10:05:04 neelin
89 * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs
90 * to that or ACR_OTHER_ERROR.
91 * Added #ifdef lint to DEFINE_ELEMENT.
92 *
93 * Revision 1.9 93/12/10 09:20:32 neelin
94 * Added acr_find_<type> routines.
95 *
96 * Revision 1.8 93/12/08 09:04:59 neelin
97 * Fixed memory leak in acr_input_group_with_max.
98 * Fixed acr_input_group_list (didn't stop reading when reached max group).
99 *
100 * Revision 1.7 93/11/30 08:57:42 neelin
101 * Added group and group list copy routines.
102 *
103 * Revision 1.6 93/11/26 18:47:51 neelin
104 * Added group and group list copy routines.
105 *
106 * Revision 1.5 93/11/25 10:36:57 neelin
107 * Fixed input_group_list (wasn't checking max properly).
108 *
109 * Revision 1.4 93/11/24 12:05:12 neelin
110 * Changed format of dump.
111 *
112 * Revision 1.3 93/11/24 11:25:38 neelin
113 * Added some group list stuff (dump, input_group_list).
114 *
115 * Revision 1.2 93/11/22 13:11:58 neelin
116 * Changed to use new Acr_Element_Id stuff
117 *
118 * Revision 1.1 93/11/19 12:48:52 neelin
119 * Initial revision
120 *
121 @COPYRIGHT :
122 Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre,
123 Montreal Neurological Institute, McGill University.
124 Permission to use, copy, modify, and distribute this
125 software and its documentation for any purpose and without
126 fee is hereby granted, provided that the above copyright
127 notice appear in all copies. The author and McGill University
128 make no representations about the suitability of this
129 software for any purpose. It is provided "as is" without
130 express or implied warranty.
131 ---------------------------------------------------------------------------- */
132
133 #include <stdlib.h>
134 #include <stdio.h>
135 #include <ctype.h>
136 #include <string.h>
137 #include <acr_nema.h>
138
139 /* Private functions */
140 static void steal_element(Acr_Group group, Acr_Element element,
141 Acr_Element previous);
142 static void remove_element(Acr_Group group, Acr_Element element,
143 Acr_Element previous);
144 static Acr_Status insert_element(Acr_Group group, Acr_Element element,
145 Acr_Element previous);
146 static void update_group_length_element(Acr_Group group,
147 Acr_VR_encoding_type vr_encoding);
148 static Acr_Status acr_input_group_with_max(Acr_File *afp, Acr_Group *group,
149 int max_group_id);
150
151 acr_name_proc_t _acr_name_proc = NULL;
152
153
154 /* ----------------------------- MNI Header -----------------------------------
155 @NAME : acr_create_group
156 @INPUT : group_id
157 @OUTPUT : (none)
158 @RETURNS : Pointer to group structure
159 @DESCRIPTION: Creates an acr-nema group structure
160 @METHOD :
161 @GLOBALS :
162 @CALLS :
163 @CREATED : November 10, 1993 (Peter Neelin)
164 @MODIFIED : February 4, 1997 (P.N.)
165 ---------------------------------------------------------------------------- */
acr_create_group(int group_id)166 Acr_Group acr_create_group(int group_id)
167 {
168 Acr_Group group;
169 Acr_Element length_element;
170 long group_length = 0;
171
172 /* Allocate the group */
173 group = MALLOC(sizeof(*group));
174
175 /* Create a length element */
176 group_length = 0;
177 length_element =
178 acr_create_element(group_id, ACR_EID_GRPLEN, ACR_VR_UL,
179 (long) ACR_SIZEOF_LONG,
180 acr_memdup((size_t) ACR_SIZEOF_LONG, &group_length));
181
182 /* Assign fields */
183 group->group_id = group_id;
184 group->nelements = 1;
185 group->implicit_total_length =
186 acr_get_element_total_length(length_element, ACR_IMPLICIT_VR);
187 group->explicit_total_length =
188 acr_get_element_total_length(length_element, ACR_EXPLICIT_VR);
189 group->list_head = length_element;
190 group->list_tail = length_element;
191 group->next = NULL;
192
193 return group;
194 }
195
196 /* ----------------------------- MNI Header -----------------------------------
197 @NAME : acr_delete_group
198 @INPUT : group
199 @OUTPUT : (none)
200 @RETURNS : (nothing)
201 @DESCRIPTION: Deletes an acr-nema group structure (freeing the element list)
202 @METHOD :
203 @GLOBALS :
204 @CALLS :
205 @CREATED : November 10, 1993 (Peter Neelin)
206 @MODIFIED :
207 ---------------------------------------------------------------------------- */
acr_delete_group(Acr_Group group)208 void acr_delete_group(Acr_Group group)
209 {
210 acr_delete_element_list(group->list_head);
211
212 FREE(group);
213
214 return;
215 }
216
217 /* ----------------------------- MNI Header -----------------------------------
218 @NAME : acr_delete_group_list
219 @INPUT : group_list
220 @OUTPUT : (none)
221 @RETURNS : (nothing)
222 @DESCRIPTION: Delete a list of acr-nema group
223 @METHOD :
224 @GLOBALS :
225 @CALLS :
226 @CREATED : November 10, 1993 (Peter Neelin)
227 @MODIFIED :
228 ---------------------------------------------------------------------------- */
acr_delete_group_list(Acr_Group group_list)229 void acr_delete_group_list(Acr_Group group_list)
230 {
231 Acr_Group next, cur;
232
233 /* Check for null group */
234 if (group_list == NULL) return;
235
236 /* Loop through the list, deleting groups */
237 next = group_list;
238 do {
239 cur = next;
240 next = cur->next;
241 acr_delete_group(cur);
242 } while (next != NULL);
243
244 return;
245 }
246
247 /* ----------------------------- MNI Header -----------------------------------
248 @NAME : acr_copy_group
249 @INPUT : group
250 @OUTPUT : (none)
251 @RETURNS : (nothing)
252 @DESCRIPTION: Makes a copy of an acr-nema group structure
253 @METHOD :
254 @GLOBALS :
255 @CALLS :
256 @CREATED : November 26, 1993 (Peter Neelin)
257 @MODIFIED :
258 ---------------------------------------------------------------------------- */
acr_copy_group(Acr_Group group)259 Acr_Group acr_copy_group(Acr_Group group)
260 {
261 Acr_Group copy;
262 Acr_Element cur;
263
264 /* Create the group */
265 copy = acr_create_group(acr_get_group_group(group));
266
267 /* Get the second element (first element is always there) */
268 cur = acr_get_element_next(group->list_head);
269 while (cur != NULL) {
270 acr_group_add_element(copy, acr_copy_element(cur));
271 cur = acr_get_element_next(cur);
272 }
273
274 return copy;
275 }
276
277 /* ----------------------------- MNI Header -----------------------------------
278 @NAME : acr_copy_group_list
279 @INPUT : group_list
280 @OUTPUT : (none)
281 @RETURNS : (nothing)
282 @DESCRIPTION: Make a copy of a group list
283 @METHOD :
284 @GLOBALS :
285 @CALLS :
286 @CREATED : November 26, 1993 (Peter Neelin)
287 @MODIFIED :
288 ---------------------------------------------------------------------------- */
acr_copy_group_list(Acr_Group group_list)289 Acr_Group acr_copy_group_list(Acr_Group group_list)
290 {
291 Acr_Group copy_list;
292 Acr_Group copy_group;
293 Acr_Group cur;
294
295 /* Create first group */
296 copy_list = copy_group = acr_copy_group(group_list);
297
298 /* Loop through groups */
299 cur = acr_get_group_next(group_list);
300 while (cur != NULL) {
301 acr_set_group_next(copy_group, acr_copy_group(cur));
302 copy_group = acr_get_group_next(copy_group);
303 cur = acr_get_group_next(cur);
304 }
305
306 return copy_list;
307
308 }
309
310 /* ----------------------------- MNI Header -----------------------------------
311 @NAME : steal_element
312 @INPUT : group
313 element - element to remove
314 previous - pointer to previous element or NULL if beginning
315 of group element list
316 @OUTPUT : (none)
317 @RETURNS : (nothing)
318 @DESCRIPTION: Steal an element from a group (remove it without deleting it).
319 The caller must free the element themselves.
320 @METHOD :
321 @GLOBALS :
322 @CALLS :
323 @CREATED : November 6, 1998 (Peter Neelin)
324 @MODIFIED :
325 ---------------------------------------------------------------------------- */
steal_element(Acr_Group group,Acr_Element element,Acr_Element previous)326 static void steal_element(Acr_Group group, Acr_Element element,
327 Acr_Element previous)
328 {
329 Acr_Element next;
330
331 /* Get pointer to next element */
332 next = acr_get_element_next(element);
333
334 /* Update the previous element or list head */
335 if (previous != NULL)
336 acr_set_element_next(previous, next);
337 else
338 group->list_head = next;
339
340 /* Check for an element at the tail */
341 if (next == NULL)
342 group->list_tail = previous;
343
344 /* Update the group fields */
345 group->nelements--;
346 group->implicit_total_length -=
347 acr_get_element_total_length(element, ACR_IMPLICIT_VR);
348 group->explicit_total_length -=
349 acr_get_element_total_length(element, ACR_EXPLICIT_VR);
350
351 /* Update the group length element */
352 update_group_length_element(group,
353 acr_get_element_vr_encoding(group->list_head));
354
355 }
356
357 /* ----------------------------- MNI Header -----------------------------------
358 @NAME : remove_element
359 @INPUT : group
360 element - element to remove
361 previous - pointer to previous element or NULL if beginning
362 of group element list
363 @OUTPUT : (none)
364 @RETURNS : (nothing)
365 @DESCRIPTION: Remove an element from a group.
366 @METHOD :
367 @GLOBALS :
368 @CALLS :
369 @CREATED : June 17, 1997 (Peter Neelin)
370 @MODIFIED :
371 ---------------------------------------------------------------------------- */
remove_element(Acr_Group group,Acr_Element element,Acr_Element previous)372 static void remove_element(Acr_Group group, Acr_Element element,
373 Acr_Element previous)
374 {
375
376 /* Get rid of the old element from the group */
377 steal_element(group, element, previous);
378
379 /* Delete the old element */
380 acr_delete_element(element);
381
382 }
383
384 /* ----------------------------- MNI Header -----------------------------------
385 @NAME : insert_element
386 @INPUT : group
387 element - element to insert
388 previous - pointer to previous element or NULL if beginning
389 of group element list
390 @OUTPUT : (none)
391 @RETURNS : Acr_Status
392 @DESCRIPTION: Insert an element into a group.
393 @METHOD :
394 @GLOBALS :
395 @CALLS :
396 @CREATED : June 17, 1997 (Peter Neelin)
397 @MODIFIED :
398 ---------------------------------------------------------------------------- */
insert_element(Acr_Group group,Acr_Element element,Acr_Element previous)399 static Acr_Status insert_element(Acr_Group group, Acr_Element element,
400 Acr_Element previous)
401 {
402 Acr_Element next;
403 long length;
404
405 /* Update the pointers */
406 if (previous != NULL) { /* Middle or tail of list */
407 next = acr_get_element_next(previous);
408 acr_set_element_next(previous, element);
409 }
410 else { /* Head of list */
411 next = group->list_head;
412 group->list_head = element;
413 }
414 acr_set_element_next(element, next);
415
416 /* Check for the tail */
417 if (next == NULL) {
418 group->list_tail = element;
419 }
420
421 /* Update the group fields */
422 group->nelements++;
423 length = acr_get_element_total_length(element, ACR_IMPLICIT_VR);
424 if (length <= 0) {
425 return (ACR_OTHER_ERROR);
426 }
427 group->implicit_total_length += length;
428
429 length = acr_get_element_total_length(element, ACR_EXPLICIT_VR);
430 if (length <= 0) {
431 return (ACR_OTHER_ERROR);
432 }
433 group->explicit_total_length += length;
434
435
436 /* Update the length element */
437 update_group_length_element(group,
438 acr_get_element_vr_encoding(group->list_head));
439 return (ACR_OK);
440 }
441
442 /* ----------------------------- MNI Header -----------------------------------
443 @NAME : acr_group_insert_element
444 @INPUT : group
445 element
446 @OUTPUT : (none)
447 @RETURNS : Acr_Status
448 @DESCRIPTION: Insert an element into a group. If an element of the same
449 id already exists in the list, it is removed and deleted.
450 @METHOD :
451 @GLOBALS :
452 @CALLS :
453 @CREATED : June 17, 1997 (Peter Neelin)
454 @MODIFIED :
455 ---------------------------------------------------------------------------- */
acr_group_insert_element(Acr_Group group,Acr_Element element)456 Acr_Status acr_group_insert_element(Acr_Group group,
457 Acr_Element element)
458 {
459 Acr_Element next_element, prev_element, cur_element;
460 int element_id;
461
462 /* Check that the element belongs in this group */
463 if (group->group_id != acr_get_element_group(element)) {
464 (void) fprintf(stderr,
465 "ACR error: Cannot add element %d (group %d) to group %d\n",
466 acr_get_element_element(element),
467 acr_get_element_group(element),
468 group->group_id);
469 exit(EXIT_FAILURE);
470 }
471
472 /* Get element id */
473 element_id = acr_get_element_element(element);
474
475 /* Check that new element has id > group length element id */
476 if (element_id < ACR_EID_GRPLEN) {
477 (void) fprintf(stderr,
478 "ACR error: Cannot add element id %d <= length id (%d) to group %d\n",
479 element_id, ACR_EID_GRPLEN, group->group_id);
480 exit(EXIT_FAILURE);
481 }
482
483 /* Check whether the the element should be added after the last element */
484 if (acr_get_element_element(group->list_tail) < element_id) {
485 prev_element = group->list_tail;
486 next_element = NULL;
487 }
488
489 /* Otherwise, search for the appropriate location */
490 else {
491 prev_element = NULL;
492 next_element = group->list_head;
493 while ((next_element != NULL) &&
494 (acr_get_element_element(next_element) < element_id)) {
495 prev_element = next_element;
496 next_element = acr_get_element_next(next_element);
497 }
498 }
499
500 /* Check for an existing element and get rid of it */
501 if ((next_element != NULL) &&
502 (acr_get_element_element(next_element) == element_id)) {
503
504 /* Set pointers and get rid of the old element */
505 cur_element = next_element;
506 next_element = acr_get_element_next(cur_element);
507 remove_element(group, cur_element, prev_element);
508
509 }
510
511 /* Insert the new element */
512 return insert_element(group, element, prev_element);
513
514 }
515
516 /* ----------------------------- MNI Header -----------------------------------
517 @NAME : acr_group_add_element
518 @INPUT : group
519 element
520 @OUTPUT : (none)
521 @RETURNS : Acr_Status
522 @DESCRIPTION: Add an element to an acr-nema group
523 @METHOD :
524 @GLOBALS :
525 @CALLS :
526 @CREATED : November 10, 1993 (Peter Neelin)
527 @MODIFIED :
528 ---------------------------------------------------------------------------- */
acr_group_add_element(Acr_Group group,Acr_Element element)529 Acr_Status acr_group_add_element(Acr_Group group, Acr_Element element)
530 {
531 /* Check that the element belongs in this group */
532 if (group->group_id != acr_get_element_group(element)) {
533 (void) fprintf(stderr,
534 "ACR error: Cannot add element %d (group %d) to group %d\n",
535 acr_get_element_element(element),
536 acr_get_element_group(element),
537 group->group_id);
538 exit(EXIT_FAILURE);
539 }
540
541 /* Insert the element at the tail */
542 return insert_element(group, element, group->list_tail);
543 }
544
545 /* ----------------------------- MNI Header -----------------------------------
546 @NAME : acr_group_remove_element
547 @INPUT : group
548 element_id
549 @OUTPUT : (none)
550 @RETURNS : (nothing)
551 @DESCRIPTION: Remove an element from a group.
552 @METHOD :
553 @GLOBALS :
554 @CALLS :
555 @CREATED : June 17, 1997 (Peter Neelin)
556 @MODIFIED :
557 ---------------------------------------------------------------------------- */
acr_group_remove_element(Acr_Group group,int element_id)558 void acr_group_remove_element(Acr_Group group, int element_id)
559 {
560 Acr_Element next_element, prev_element;
561
562 /* Search for the appropriate location */
563 prev_element = NULL;
564 next_element = group->list_head;
565 while ((next_element != NULL) &&
566 (acr_get_element_element(next_element) != element_id)) {
567 prev_element = next_element;
568 next_element = acr_get_element_next(next_element);
569 }
570
571 /* Check for an existing element and get rid of it */
572 if ((next_element != NULL) &&
573 (acr_get_element_element(next_element) == element_id)) {
574
575 /* Set pointers and get rid of the old element */
576 remove_element(group, next_element, prev_element);
577
578 }
579
580 }
581
582 /* ----------------------------- MNI Header -----------------------------------
583 @NAME : acr_group_steal_element
584 @INPUT : group
585 element - the caller must pass an element so that we
586 know that they have a handle to it.
587 @OUTPUT : (none)
588 @RETURNS : (nothing)
589 @DESCRIPTION: Remove an element from a group without deleting it.
590 @METHOD :
591 @GLOBALS :
592 @CALLS :
593 @CREATED : November 6, 1998 (Peter Neelin)
594 @MODIFIED :
595 ---------------------------------------------------------------------------- */
acr_group_steal_element(Acr_Group group,Acr_Element element)596 void acr_group_steal_element(Acr_Group group, Acr_Element element)
597 {
598 int element_id;
599 Acr_Element next_element, prev_element;
600
601 /* Get element id from element */
602 element_id = acr_get_element_element(element);
603
604 /* Search for the appropriate location */
605 prev_element = NULL;
606 next_element = group->list_head;
607 while ((next_element != NULL) &&
608 (acr_get_element_element(next_element) != element_id)) {
609 prev_element = next_element;
610 next_element = acr_get_element_next(next_element);
611 }
612
613 /* Check for an existing element and get rid of it */
614 if ((next_element != NULL) &&
615 (acr_get_element_element(next_element) == element_id)) {
616
617 /* Set pointers and get rid of the old element */
618 steal_element(group, next_element, prev_element);
619
620 }
621
622 }
623
624 /* ----------------------------- MNI Header -----------------------------------
625 @NAME : update_group_length_element
626 @INPUT : group
627 vr_encoding - ACR_IMPLICIT_VR or ACR_EXPLICIT_VR
628 @OUTPUT : (none)
629 @RETURNS : (nothing)
630 @DESCRIPTION: Update the length element of the group according to the VR type
631 @METHOD :
632 @GLOBALS :
633 @CALLS :
634 @CREATED : February 14, 1997 (Peter Neelin)
635 @MODIFIED :
636 ---------------------------------------------------------------------------- */
update_group_length_element(Acr_Group group,Acr_VR_encoding_type vr_encoding)637 static void update_group_length_element(Acr_Group group,
638 Acr_VR_encoding_type vr_encoding)
639 {
640 Acr_Long group_length;
641 Acr_Element length_element;
642 void *group_length_data;
643
644 /* Get the element */
645 length_element = group->list_head;
646 if (length_element == NULL) return;
647 if (acr_get_element_element(length_element) != ACR_EID_GRPLEN) return;
648
649 /* Calculate the appropriate length */
650 if (vr_encoding == ACR_IMPLICIT_VR) {
651 group_length = group->implicit_total_length -
652 acr_get_element_total_length(length_element, ACR_IMPLICIT_VR);
653 }
654 else {
655 group_length = group->explicit_total_length -
656 acr_get_element_total_length(length_element, ACR_EXPLICIT_VR);
657 }
658
659 /* Update the element */
660 group_length_data = acr_get_element_data(length_element);
661 acr_put_long(acr_get_element_byte_order(length_element),
662 1, &group_length, group_length_data);
663
664 }
665
666 /* ----------------------------- MNI Header -----------------------------------
667 @NAME : acr_set_group_next
668 @INPUT : group
669 next
670 @OUTPUT : (none)
671 @RETURNS : (nothing)
672 @DESCRIPTION: Set pointer to next group for an acr-nema group
673 @METHOD :
674 @GLOBALS :
675 @CALLS :
676 @CREATED : November 10, 1993 (Peter Neelin)
677 @MODIFIED :
678 ---------------------------------------------------------------------------- */
acr_set_group_next(Acr_Group group,Acr_Group next)679 void acr_set_group_next(Acr_Group group, Acr_Group next)
680 {
681 group->next = next;
682 return;
683 }
684
685 /* ----------------------------- MNI Header -----------------------------------
686 @NAME : acr_get_group_group
687 @INPUT : group
688 @OUTPUT : (none)
689 @RETURNS : group id
690 @DESCRIPTION: Get group id for group
691 @METHOD :
692 @GLOBALS :
693 @CALLS :
694 @CREATED : November 10, 1993 (Peter Neelin)
695 @MODIFIED :
696 ---------------------------------------------------------------------------- */
acr_get_group_group(Acr_Group group)697 int acr_get_group_group(Acr_Group group)
698 {
699 return group->group_id;
700 }
701
702 /* ----------------------------- MNI Header -----------------------------------
703 @NAME : acr_get_group_element_list
704 @INPUT : group
705 @OUTPUT : (none)
706 @RETURNS : element list
707 @DESCRIPTION: Get element list for group
708 @METHOD :
709 @GLOBALS :
710 @CALLS :
711 @CREATED : November 10, 1993 (Peter Neelin)
712 @MODIFIED :
713 ---------------------------------------------------------------------------- */
acr_get_group_element_list(Acr_Group group)714 Acr_Element acr_get_group_element_list(Acr_Group group)
715 {
716 return group->list_head;
717 }
718
719 /* ----------------------------- MNI Header -----------------------------------
720 @NAME : acr_get_group_total_length
721 @INPUT : group
722 vr_encoding - ACR_EXPLICIT_VR or ACR_IMPLICIT_VR
723 @OUTPUT : (none)
724 @RETURNS : total length of group
725 @DESCRIPTION: Get total length of group
726 @METHOD :
727 @GLOBALS :
728 @CALLS :
729 @CREATED : November 10, 1993 (Peter Neelin)
730 @MODIFIED :
731 ---------------------------------------------------------------------------- */
acr_get_group_total_length(Acr_Group group,Acr_VR_encoding_type vr_encoding)732 long acr_get_group_total_length(Acr_Group group,
733 Acr_VR_encoding_type vr_encoding)
734 {
735 if (vr_encoding == ACR_IMPLICIT_VR)
736 return group->implicit_total_length;
737 else
738 return group->explicit_total_length;
739 }
740
741 /* ----------------------------- MNI Header -----------------------------------
742 @NAME : acr_get_group_nelements
743 @INPUT : group
744 @OUTPUT : (none)
745 @RETURNS : number of elements in group
746 @DESCRIPTION: Get number of elements in group
747 @METHOD :
748 @GLOBALS :
749 @CALLS :
750 @CREATED : November 10, 1993 (Peter Neelin)
751 @MODIFIED :
752 ---------------------------------------------------------------------------- */
acr_get_group_nelements(Acr_Group group)753 int acr_get_group_nelements(Acr_Group group)
754 {
755 return group->nelements;
756 }
757
758 /* ----------------------------- MNI Header -----------------------------------
759 @NAME : acr_get_group_next
760 @INPUT : group
761 @OUTPUT : (none)
762 @RETURNS : next group
763 @DESCRIPTION: Get next group for group
764 @METHOD :
765 @GLOBALS :
766 @CALLS :
767 @CREATED : November 10, 1993 (Peter Neelin)
768 @MODIFIED :
769 ---------------------------------------------------------------------------- */
acr_get_group_next(Acr_Group group)770 Acr_Group acr_get_group_next(Acr_Group group)
771 {
772 return group->next;
773 }
774
775 /* ----------------------------- MNI Header -----------------------------------
776 @NAME : acr_input_group_with_max
777 @INPUT : afp - acr file pointer
778 max_group_id - maximum group id to read in. If <= 0 then any
779 group is read in.
780 @OUTPUT : group
781 @RETURNS : status
782 @DESCRIPTION: Read in an acr-nema group with an optional maximum group id.
783 If group id exceeds max, then *group is set to NULL. If an
784 error occurs, then a group may still be returned. This routine
785 will stop reading when it reaches a watchpoint.
786 @METHOD :
787 @GLOBALS :
788 @CALLS :
789 @CREATED : November 10, 1993 (Peter Neelin)
790 @MODIFIED :
791 ---------------------------------------------------------------------------- */
acr_input_group_with_max(Acr_File * afp,Acr_Group * group,int max_group_id)792 static Acr_Status acr_input_group_with_max(Acr_File *afp, Acr_Group *group,
793 int max_group_id)
794 {
795 int group_id, element_id, next_group_id;
796 long group_length;
797 Acr_Status status;
798 Acr_Element element;
799 int have_length_element;
800 int get_more_elements;
801 Acr_VR_encoding_type vr_encoding;
802
803 /* Initialize the group pointer */
804 *group = NULL;
805
806 /* Look ahead at the next element */
807 status = acr_peek_at_next_element_id(afp, &group_id, &element_id);
808 if (status != ACR_OK) return status;
809
810 /* Check for a group past the limit */
811 if ((max_group_id > 0) && (group_id > max_group_id)) {
812 return status;
813 }
814
815 /* Check for a length element */
816 have_length_element = (element_id == ACR_EID_GRPLEN);
817
818 /* Read the length element and check it */
819 if (have_length_element) {
820 status = acr_input_element(afp, &element);
821 if (status != ACR_OK) {
822 acr_delete_element(element);
823 return status;
824 }
825 if ((acr_get_element_element(element) != ACR_EID_GRPLEN) ||
826 (acr_get_element_length(element) != ACR_SIZEOF_LONG)) {
827 if (acr_ignore_protocol_errors(afp)) {
828 group_length = 0;
829 }
830 else {
831 acr_delete_element(element);
832 status = ACR_PROTOCOL_ERROR;
833 return status;
834 }
835 }
836 else {
837 group_length = acr_get_element_long(element);
838 }
839 acr_delete_element(element);
840 }
841
842 /* Create the group */
843 *group = acr_create_group(group_id);
844
845 /* Set the VR encoding and the byte ordering for the length element
846 according to the input stream. If the vr_encoding is implicit, then
847 make the VR unknown. Note that the group will always have a length
848 element even if the input stream does not. */
849 element = acr_get_group_element_list(*group);
850 vr_encoding = acr_get_vr_encoding(afp);
851 acr_set_element_vr_encoding(element, vr_encoding);
852 acr_set_element_byte_order(element, acr_get_byte_order(afp));
853 if (vr_encoding == ACR_IMPLICIT_VR) {
854 acr_set_element_vr(element, ACR_VR_UNKNOWN);
855 }
856
857 /* Loop through elements, adding them to the list */
858 get_more_elements = (have_length_element ? (group_length > 0) : TRUE);
859 while (get_more_elements) {
860
861 /* Check for a watchpoint */
862 if (acr_get_io_watchpoint(afp) <= 0) {
863 get_more_elements = FALSE;
864 break;
865 }
866
867 /* Look ahead at next element */
868 status = acr_peek_at_next_element_id(afp, &next_group_id, &element_id);
869 if ((status != ACR_OK) || (next_group_id != group_id)) {
870 if ( status == ACR_REACHED_WATCHPOINT )
871 status = ACR_OK;
872 get_more_elements = FALSE;
873 break;
874 }
875
876 /* Read in the next element */
877 status = acr_input_element(afp, &element);
878 if (status != ACR_OK) {
879 get_more_elements = FALSE;
880 }
881
882 /* Add it to the group */
883 if (element != NULL) {
884 acr_group_add_element(*group, element);
885 if (have_length_element) {
886 group_length -=
887 acr_get_element_total_length(element, acr_get_vr_encoding(afp));
888 }
889 }
890
891 /* Check group length */
892 if (have_length_element && !acr_ignore_protocol_errors(afp)) {
893 get_more_elements = (group_length > 0);
894 }
895
896 }
897
898 /* Check that we got a full group */
899 if (have_length_element && (group_length != 0) &&
900 !acr_ignore_protocol_errors(afp)) {
901 switch (status) {
902 case ACR_OK:
903 status = ACR_PROTOCOL_ERROR;
904 break;
905 case ACR_END_OF_INPUT:
906 status = ACR_ABNORMAL_END_OF_INPUT;
907 break;
908 }
909 }
910
911 return status;
912 }
913
914 /* ----------------------------- MNI Header -----------------------------------
915 @NAME : acr_input_group
916 @INPUT : afp - acr file pointer
917 @OUTPUT : group
918 @RETURNS : status
919 @DESCRIPTION: Read in an acr-nema group
920 @METHOD :
921 @GLOBALS :
922 @CALLS :
923 @CREATED : November 10, 1993 (Peter Neelin)
924 @MODIFIED :
925 ---------------------------------------------------------------------------- */
acr_input_group(Acr_File * afp,Acr_Group * group)926 Acr_Status acr_input_group(Acr_File *afp, Acr_Group *group)
927 {
928
929 return acr_input_group_with_max(afp, group, 0);
930
931 }
932
933 /* ----------------------------- MNI Header -----------------------------------
934 @NAME : acr_output_group
935 @INPUT : afp - acr file pointer
936 group
937 @OUTPUT : (none)
938 @RETURNS : status
939 @DESCRIPTION: Write out an acr-nema group
940 @METHOD :
941 @GLOBALS :
942 @CALLS :
943 @CREATED : November 10, 1993 (Peter Neelin)
944 @MODIFIED :
945 ---------------------------------------------------------------------------- */
acr_output_group(Acr_File * afp,Acr_Group group)946 Acr_Status acr_output_group(Acr_File *afp, Acr_Group group)
947 {
948 long ielement, nelements;
949 Acr_Element cur, next;
950 Acr_Status status;
951
952 /* Update the length element */
953 update_group_length_element(group, acr_get_vr_encoding(afp));
954
955 /* Loop through the elements of the group, writing them out */
956 nelements = acr_get_group_nelements(group);
957 next = acr_get_group_element_list(group);
958 for (ielement=0; ielement < nelements && next != NULL; ielement++) {
959 cur = next;
960 next = cur->next;
961 status = acr_output_element(afp, cur);
962 if (status != ACR_OK) {
963 return status;
964 }
965 }
966
967 /* Check for a bogus group (the true number of elements is different from
968 nelements) */
969 if ((ielement < nelements) || (next != NULL)) {
970 status = ACR_OTHER_ERROR;
971 return status;
972 }
973
974 return status;
975
976 }
977
978 /* ----------------------------- MNI Header -----------------------------------
979 @NAME : acr_input_group_list
980 @INPUT : afp - acr file pointer
981 max_group_id - maximum group id to read in. If <= 0 then all
982 groups are read in. If max_group_id is not a group id in the
983 input stream, then the input stream is left with the first
984 element of the next group missing (it gets read here and
985 is not put back), so no more groups can be read in.
986 @OUTPUT : group_list
987 @RETURNS : status
988 @DESCRIPTION: Read in a list of acr-nema groups. If a watchpoint is set
989 on the input handle, then group reading will stop when it is
990 reached, although at least one group will be read in.
991 @METHOD :
992 @GLOBALS :
993 @CALLS :
994 @CREATED : November 24, 1993 (Peter Neelin)
995 @MODIFIED :
996 ---------------------------------------------------------------------------- */
acr_input_group_list(Acr_File * afp,Acr_Group * group_list,int max_group_id)997 Acr_Status acr_input_group_list(Acr_File *afp, Acr_Group *group_list,
998 int max_group_id)
999 {
1000 Acr_Group cur_group, next_group;
1001 Acr_Status status;
1002
1003 /* Initialize the group list */
1004 *group_list = NULL;
1005
1006 /* Read in the first group */
1007 status = acr_input_group_with_max(afp, &next_group, max_group_id);
1008
1009 /* Set up pointers */
1010 *group_list = cur_group = next_group;
1011
1012 /* Loop, reading groups */
1013 while ((status == ACR_OK) && (cur_group != NULL) &&
1014 ((max_group_id <= 0) ||
1015 (acr_get_group_group(cur_group) < max_group_id))) {
1016
1017 /* Check for a watchpoint */
1018 if (acr_get_io_watchpoint(afp) <= 0) {
1019 break;
1020 }
1021
1022 /* Read in the next group */
1023 status = acr_input_group_with_max(afp, &next_group, max_group_id);
1024
1025 /* Add it to the list */
1026 acr_set_group_next(cur_group, next_group);
1027 cur_group = next_group;
1028
1029 }
1030
1031 return status;
1032
1033 }
1034
1035 /* ----------------------------- MNI Header -----------------------------------
1036 @NAME : acr_find_group
1037 @INPUT : group_list
1038 group_id
1039 @OUTPUT : (none)
1040 @RETURNS : gropu pointer
1041 @DESCRIPTION: Find a group in a group list
1042 @METHOD :
1043 @GLOBALS :
1044 @CALLS :
1045 @CREATED : November 6, 1998 (Peter Neelin)
1046 @MODIFIED :
1047 ---------------------------------------------------------------------------- */
acr_find_group(Acr_Group group_list,int group_id)1048 Acr_Group acr_find_group(Acr_Group group_list, int group_id)
1049 {
1050 Acr_Group group;
1051 int next_id;
1052
1053 /* Search through groups for group id */
1054 group = group_list;
1055 if (group != NULL)
1056 next_id = acr_get_group_group(group);
1057 else
1058 next_id = 0;
1059 while ((next_id != group_id) && (group != NULL)) {
1060 group = acr_get_group_next(group);
1061 if (group != NULL)
1062 next_id = acr_get_group_group(group);
1063 }
1064
1065 return group;
1066
1067 }
1068
1069 /* ----------------------------- MNI Header -----------------------------------
1070 @NAME : acr_find_group_element
1071 @INPUT : group_list
1072 elid
1073 @OUTPUT : (none)
1074 @RETURNS : element pointer
1075 @DESCRIPTION: Find an element in a group list
1076 @METHOD :
1077 @GLOBALS :
1078 @CALLS :
1079 @CREATED : November 10, 1993 (Peter Neelin)
1080 @MODIFIED :
1081 ---------------------------------------------------------------------------- */
acr_find_group_element(Acr_Group group_list,Acr_Element_Id elid)1082 Acr_Element acr_find_group_element(Acr_Group group_list,
1083 Acr_Element_Id elid)
1084 {
1085 Acr_Group group;
1086
1087 /* Find the group */
1088 group = acr_find_group(group_list, elid->group_id);
1089
1090 /* If not found return NULL */
1091 if (group == NULL) return NULL;
1092
1093 /* Search through element list for element */
1094 return acr_find_element_id(acr_get_group_element_list(group), elid);
1095
1096 }
1097
1098 /* ----------------------------- MNI Header -----------------------------------
1099 @NAME : acr_dump_group_list
1100 @INPUT : file_pointer - where output should go
1101 group_list
1102 @OUTPUT : (none)
1103 @RETURNS : (nothing)
1104 @DESCRIPTION: Dump information from an acr-nema group list
1105 @METHOD :
1106 @GLOBALS :
1107 @CALLS :
1108 @CREATED : November 24, 1993 (Peter Neelin)
1109 @MODIFIED :
1110 ---------------------------------------------------------------------------- */
acr_dump_group_list(FILE * file_pointer,Acr_Group group_list)1111 void acr_dump_group_list(FILE *file_pointer, Acr_Group group_list)
1112 {
1113 Acr_Group cur_group;
1114
1115 /* Check for empty list */
1116 cur_group = group_list;
1117 if (cur_group == NULL) {
1118 (void) fprintf(file_pointer,"\nEmpty group list\n\n");
1119 return;
1120 }
1121
1122 /* Loop over groups */
1123 while (cur_group != NULL) {
1124
1125 /* Print the group id */
1126 (void) fprintf(file_pointer, "\nGroup 0x%04x :\n\n",
1127 acr_get_group_group(cur_group));
1128
1129 /* Print the elements */
1130 acr_dump_element_list(file_pointer,
1131 acr_get_group_element_list(cur_group));
1132
1133 /* Go to the next group */
1134 cur_group = acr_get_group_next(cur_group);
1135 }
1136
1137 /* Print a blank line after dump */
1138 (void) fprintf(file_pointer, "\n");
1139
1140 /* Flush the buffer */
1141 (void) fflush(file_pointer);
1142
1143 return;
1144
1145 }
1146
1147 /* ----------------------------- MNI Header -----------------------------------
1148 @NAME : acr_find_short
1149 @INPUT : group_list
1150 elid
1151 default_value
1152 @OUTPUT : (none)
1153 @RETURNS : Element value or default_value if element not found
1154 @DESCRIPTION: Find an element in a group list and return its value (assuming
1155 that it is stored as a binary short).
1156 @METHOD :
1157 @GLOBALS :
1158 @CALLS :
1159 @CREATED : December 10, 1993 (Peter Neelin)
1160 @MODIFIED :
1161 ---------------------------------------------------------------------------- */
acr_find_short(Acr_Group group_list,Acr_Element_Id elid,Acr_Short default_value)1162 Acr_Short acr_find_short(Acr_Group group_list, Acr_Element_Id elid,
1163 Acr_Short default_value)
1164 {
1165 Acr_Element element;
1166
1167 element = acr_find_group_element(group_list, elid);
1168 if (element != NULL && acr_get_element_length(element) > 0)
1169 return acr_get_element_short(element);
1170 else
1171 return default_value;
1172 }
1173
1174 /* ----------------------------- MNI Header -----------------------------------
1175 @NAME : acr_find_long
1176 @INPUT : group_list
1177 elid
1178 default_value
1179 @OUTPUT : (none)
1180 @RETURNS : Element value or default_value if element not found
1181 @DESCRIPTION: Find an element in a group list and return its value (assuming
1182 that it is stored as a binary long).
1183 @METHOD :
1184 @GLOBALS :
1185 @CALLS :
1186 @CREATED : December 10, 1993 (Peter Neelin)
1187 @MODIFIED :
1188 ---------------------------------------------------------------------------- */
acr_find_long(Acr_Group group_list,Acr_Element_Id elid,Acr_Long default_value)1189 Acr_Long acr_find_long(Acr_Group group_list, Acr_Element_Id elid,
1190 Acr_Long default_value)
1191 {
1192 Acr_Element element;
1193
1194 element = acr_find_group_element(group_list, elid);
1195 if (element != NULL && acr_get_element_length(element) > 0)
1196 return acr_get_element_long(element);
1197 else
1198 return default_value;
1199 }
1200
1201 /* ----------------------------- MNI Header -----------------------------------
1202 @NAME : acr_find_int
1203 @INPUT : group_list
1204 elid
1205 default_value
1206 @OUTPUT : (none)
1207 @RETURNS : Element value or default_value if element not found
1208 @DESCRIPTION: Find an element in a group list and return its value (assuming
1209 that it is stored as an ascii integer).
1210 @METHOD :
1211 @GLOBALS :
1212 @CALLS :
1213 @CREATED : December 10, 1993 (Peter Neelin)
1214 @MODIFIED :
1215 ---------------------------------------------------------------------------- */
acr_find_int(Acr_Group group_list,Acr_Element_Id elid,int default_value)1216 int acr_find_int(Acr_Group group_list, Acr_Element_Id elid,
1217 int default_value)
1218 {
1219 Acr_Element element;
1220
1221 element = acr_find_group_element(group_list, elid);
1222 if (element != NULL && acr_get_element_length(element) > 0)
1223 return (int) acr_get_element_numeric(element);
1224 else
1225 return default_value;
1226 }
1227
1228 /* ----------------------------- MNI Header -----------------------------------
1229 @NAME : acr_find_double
1230 @INPUT : group_list
1231 elid
1232 default_value
1233 @OUTPUT : (none)
1234 @RETURNS : Element value or default_value if element not found
1235 @DESCRIPTION: Find an element in a group list and return its value (assuming
1236 that it is stored as an ascii double).
1237 @METHOD :
1238 @GLOBALS :
1239 @CALLS :
1240 @CREATED : December 10, 1993 (Peter Neelin)
1241 @MODIFIED :
1242 ---------------------------------------------------------------------------- */
acr_find_double(Acr_Group group_list,Acr_Element_Id elid,Acr_Double default_value)1243 Acr_Double acr_find_double(Acr_Group group_list, Acr_Element_Id elid,
1244 Acr_Double default_value)
1245 {
1246 Acr_Element element;
1247
1248 element = acr_find_group_element(group_list, elid);
1249 if (element != NULL && acr_get_element_length(element) > 0)
1250 return (Acr_Double)acr_get_element_numeric(element);
1251 else
1252 return default_value;
1253 }
1254
1255 /* ----------------------------- MNI Header -----------------------------------
1256 @NAME : acr_find_string
1257 @INPUT : group_list
1258 elid
1259 default_value
1260 @OUTPUT : (none)
1261 @RETURNS : Element value or default_value if element not found
1262 @DESCRIPTION: Find an element in a group list and return its value (assuming
1263 that it is stored as an ascii string).
1264 @METHOD :
1265 @GLOBALS :
1266 @CALLS :
1267 @CREATED : December 10, 1993 (Peter Neelin)
1268 @MODIFIED :
1269 ---------------------------------------------------------------------------- */
acr_find_string(Acr_Group group_list,Acr_Element_Id elid,Acr_String default_value)1270 Acr_String acr_find_string(Acr_Group group_list, Acr_Element_Id elid,
1271 Acr_String default_value)
1272 {
1273 Acr_Element element;
1274
1275 element = acr_find_group_element(group_list, elid);
1276 if (element != NULL) /* Allow zero-length strings */
1277 return acr_get_element_string(element);
1278 else
1279 return default_value;
1280 }
1281
1282 /* ----------------------------- MNI Header -----------------------------------
1283 @NAME : acr_insert_element_into_group_list
1284 @INPUT : group_list - list in which element should be inserted
1285 (can be NULL)
1286 element - element to insert
1287 @OUTPUT : group_list - modified group list
1288 @RETURNS : Acr_Status
1289 @DESCRIPTION: Insert an element into a group list. If the group_list is NULL,
1290 then it is created. Note that the element is not copied, it is
1291 just inserted into the list, so it should not be modified after
1292 insertion into the list. If an element of the same id already
1293 exists in the list, it is removed and deleted.
1294 @METHOD :
1295 @GLOBALS :
1296 @CALLS :
1297 @CREATED : June 17, 1997 (Peter Neelin)
1298 @MODIFIED :
1299 ---------------------------------------------------------------------------- */
acr_insert_element_into_group_list(Acr_Group * group_list,Acr_Element element)1300 Acr_Status acr_insert_element_into_group_list(Acr_Group *group_list,
1301 Acr_Element element)
1302 {
1303 Acr_Group group, next_group, prev_group;
1304 int group_id;
1305
1306 /* Get group and element id */
1307 group_id = acr_get_element_group(element);
1308
1309 /* Search for the appropriate group */
1310 prev_group = NULL;
1311 next_group = *group_list;
1312 while ((next_group != NULL) &&
1313 (acr_get_group_group(next_group) < group_id)) {
1314 prev_group = next_group;
1315 next_group = acr_get_group_next(next_group);
1316 }
1317
1318 /* Check if we have the right group */
1319 if ((next_group != NULL) &&
1320 (acr_get_group_group(next_group) == group_id)) {
1321 group = next_group;
1322 }
1323
1324 /* If not, create a new group and insert it in the list */
1325 else {
1326
1327 /* Create a group */
1328 group = acr_create_group(group_id);
1329
1330 /* Insert it in the list */
1331 acr_set_group_next(group, next_group);
1332 if (prev_group != NULL) {
1333 acr_set_group_next(prev_group, group);
1334 }
1335 else {
1336 *group_list = group;
1337 }
1338
1339 }
1340
1341 /* Insert the element into the appropriate group */
1342 return acr_group_insert_element(group, element);
1343
1344 }
1345
1346 /* ----------------------------- MNI Header -----------------------------------
1347 @NAME : acr_insert_short
1348 @INPUT : group_list - may be NULL if list empty
1349 elid
1350 value
1351 @OUTPUT : group_list - modified group list
1352 @RETURNS : Acr_Status
1353 @DESCRIPTION: Creates and inserts an element into a group list.
1354 @METHOD :
1355 @GLOBALS :
1356 @CALLS :
1357 @CREATED : June 17, 1997 (Peter Neelin)
1358 @MODIFIED :
1359 ---------------------------------------------------------------------------- */
acr_insert_short(Acr_Group * group_list,Acr_Element_Id elid,Acr_Short value)1360 Acr_Status acr_insert_short(Acr_Group *group_list, Acr_Element_Id elid,
1361 Acr_Short value)
1362 {
1363 Acr_Element element;
1364
1365 element = acr_create_element_short(elid, value);
1366 return acr_insert_element_into_group_list(group_list, element);
1367
1368 }
1369
1370 /* ----------------------------- MNI Header -----------------------------------
1371 @NAME : acr_insert_long
1372 @INPUT : group_list - may be NULL if list empty
1373 elid
1374 value
1375 @OUTPUT : group_list - modified group list
1376 @RETURNS : Acr_Status
1377 @DESCRIPTION: Creates and inserts an element into a group list.
1378 @METHOD :
1379 @GLOBALS :
1380 @CALLS :
1381 @CREATED : June 17, 1997 (Peter Neelin)
1382 @MODIFIED :
1383 ---------------------------------------------------------------------------- */
acr_insert_long(Acr_Group * group_list,Acr_Element_Id elid,Acr_Long value)1384 Acr_Status acr_insert_long(Acr_Group *group_list, Acr_Element_Id elid,
1385 Acr_Long value)
1386 {
1387 Acr_Element element;
1388
1389 element = acr_create_element_long(elid, value);
1390 return acr_insert_element_into_group_list(group_list, element);
1391
1392 }
1393
1394 /* ----------------------------- MNI Header -----------------------------------
1395 @NAME : acr_insert_double
1396 @INPUT : group_list - may be NULL if list empty
1397 elid
1398 nvalues
1399 values
1400 @OUTPUT : group_list - modified group list
1401 @RETURNS : Acr_Status
1402 @DESCRIPTION: Creates and inserts an element into a group list.
1403 @METHOD :
1404 @GLOBALS :
1405 @CALLS :
1406 @CREATED : April 8, 2006 (Bert Vincent)
1407 @MODIFIED :
1408 ---------------------------------------------------------------------------- */
acr_insert_double(Acr_Group * group_list,Acr_Element_Id elid,int nvalues,Acr_Double * values)1409 Acr_Status acr_insert_double(Acr_Group *group_list, Acr_Element_Id elid,
1410 int nvalues, Acr_Double *values)
1411 {
1412 Acr_Element element;
1413 element = acr_create_element_double(elid, nvalues, values);
1414 return acr_insert_element_into_group_list(group_list, element);
1415 }
1416
1417 /* ----------------------------- MNI Header -----------------------------------
1418 @NAME : acr_insert_numeric
1419 @INPUT : group_list - may be NULL if list empty
1420 elid
1421 value
1422 @OUTPUT : group_list - modified group list
1423 @RETURNS : Acr_Status
1424 @DESCRIPTION: Creates and inserts an element into a group list.
1425 @METHOD :
1426 @GLOBALS :
1427 @CALLS :
1428 @CREATED : June 17, 1997 (Peter Neelin)
1429 @MODIFIED :
1430 ---------------------------------------------------------------------------- */
acr_insert_numeric(Acr_Group * group_list,Acr_Element_Id elid,double value)1431 Acr_Status acr_insert_numeric(Acr_Group *group_list,
1432 Acr_Element_Id elid,
1433 double value)
1434 {
1435 Acr_Element element;
1436
1437 element = acr_create_element_numeric(elid, value);
1438 return acr_insert_element_into_group_list(group_list, element);
1439
1440 }
1441
1442 /* ----------------------------- MNI Header -----------------------------------
1443 @NAME : acr_insert_string
1444 @INPUT : group_list - may be NULL if list empty
1445 elid
1446 value
1447 @OUTPUT : group_list - modified group list
1448 @RETURNS : Acr_Status
1449 @DESCRIPTION: Creates and inserts an element into a group list.
1450 @METHOD :
1451 @GLOBALS :
1452 @CALLS :
1453 @CREATED : June 17, 1997 (Peter Neelin)
1454 @MODIFIED :
1455 ---------------------------------------------------------------------------- */
acr_insert_string(Acr_Group * group_list,Acr_Element_Id elid,Acr_String value)1456 Acr_Status acr_insert_string(Acr_Group *group_list,
1457 Acr_Element_Id elid,
1458 Acr_String value)
1459 {
1460 Acr_Element element;
1461
1462 element = acr_create_element_string(elid, value);
1463 return acr_insert_element_into_group_list(group_list, element);
1464
1465 }
1466
1467 /* ----------------------------- MNI Header -----------------------------------
1468 @NAME : acr_insert_sequence
1469 @INPUT : group_list - may be NULL if list empty
1470 elid
1471 itemlist
1472 @OUTPUT : group_list - modified group list
1473 @RETURNS : Acr_Status
1474 @DESCRIPTION: Creates and inserts an element into a group list.
1475 @METHOD :
1476 @GLOBALS :
1477 @CALLS :
1478 @CREATED : June 17, 1997 (Peter Neelin)
1479 @MODIFIED :
1480 ---------------------------------------------------------------------------- */
acr_insert_sequence(Acr_Group * group_list,Acr_Element_Id elid,Acr_Element itemlist)1481 Acr_Status acr_insert_sequence(Acr_Group *group_list,
1482 Acr_Element_Id elid,
1483 Acr_Element itemlist)
1484 {
1485 Acr_Element element;
1486
1487 element = acr_create_element_sequence(elid, itemlist);
1488 return acr_insert_element_into_group_list(group_list, element);
1489
1490 }
1491
1492 /* ----------------------------- MNI Header -----------------------------------
1493 @NAME : acr_test_dicom_file
1494 @INPUT : afp
1495 @OUTPUT : (none)
1496 @RETURNS : status
1497 @DESCRIPTION: Tests for a dicom file input, as well as setting the byte
1498 order and VR encoding.
1499 @METHOD : Check the byte order and t
1500 This function is in this file because it does not really have
1501 a better place to live: It depends on the group reading code
1502 (and so should not live in acr_io.c) and is independent of
1503 the other dicom code (and so should not live there).
1504 @GLOBALS :
1505 @CALLS : acr_test_byte_order, acr_input_group_list
1506 @CREATED : November 8, 2001 (Peter Neelin)
1507 @MODIFIED :
1508 ---------------------------------------------------------------------------- */
acr_test_dicom_file(Acr_File * afp)1509 Acr_Status acr_test_dicom_file(Acr_File *afp)
1510 {
1511 #define DICOM_FILE_MAGIC_OFFSET 128
1512 #define DICOM_MAGIC_STRING "DICM"
1513 #define DICOM_MAGIC_LEN 4
1514 #define DICOM_FILE_GROUP 0x2
1515
1516 unsigned char buffer[DICOM_FILE_MAGIC_OFFSET+DICOM_MAGIC_LEN];
1517 Acr_Status status;
1518 long buflen;
1519 Acr_Group group_list;
1520
1521 /* Read in up to magic */
1522 status = acr_read_buffer(afp, buffer, sizeof(buffer), &buflen);
1523 if (status != ACR_OK) return status;
1524
1525 /* Check for the magic. If it is not there, put the data back and
1526 then test the byte order. */
1527 if (strncmp((char *) &buffer[DICOM_FILE_MAGIC_OFFSET], DICOM_MAGIC_STRING,
1528 DICOM_MAGIC_LEN) != 0) {
1529 status = acr_unget_buffer(afp, buffer, buflen);
1530 if (status != ACR_OK) return status;
1531 return acr_test_byte_order(afp);
1532 }
1533
1534 /* Read in group 2.
1535 We could get the transfer syntax in the group at this point,
1536 or just use the test heuristic from acr_test_byte_order. It seems
1537 safer to trust the heuristic than the file writer, so we will ignore
1538 the contents of the group. */
1539 status = acr_test_byte_order(afp);
1540 if (status != ACR_OK) return status;
1541 status = acr_input_group_list(afp, &group_list, DICOM_FILE_GROUP);
1542 acr_delete_group_list(group_list);
1543 if (status != ACR_OK) return status;
1544
1545 /* Test the byte order for the remainder of the file */
1546 status = acr_test_byte_order(afp);
1547 if (status != ACR_OK) return status;
1548
1549 return status;
1550 }
1551
1552