DETMON Pipeline Reference Manual  1.2.7
irplib_framelist.c
1 /*
2  * This file is part of the irplib package
3  * Copyright (C) 2002,2003 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 
26 /*-----------------------------------------------------------------------------
27  Includes
28  -----------------------------------------------------------------------------*/
29 
30 #include "irplib_framelist.h"
31 #include "irplib_utils.h"
32 #include <cpl.h>
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <regex.h>
38 #include <math.h>
39 #include <assert.h>
40 
41 
42 /*-----------------------------------------------------------------------------
43  New types
44  -----------------------------------------------------------------------------*/
45 
46 /* @cond */
47 struct _irplib_framelist_ {
48  int size;
49  cpl_frame ** frame;
50  cpl_propertylist ** propertylist;
51 
52 };
53 /* @endcond */
54 
55 /*-----------------------------------------------------------------------------
56  Private funcions
57  -----------------------------------------------------------------------------*/
58 
59 static void irplib_framelist_set_size(irplib_framelist *)
60 #if defined __GNUC__ && __GNUC__ >= 4
61  __attribute__((nonnull))
62 #endif
63 ;
64 
65 static cpl_boolean irplib_property_equal(const cpl_propertylist *,
66  const cpl_propertylist *,
67  const char *, cpl_type, double,
68  char **, char **)
69 #if defined __GNUC__ && __GNUC__ >= 4
70  __attribute__((nonnull))
71 #endif
72 ;
73 
74 /*----------------------------------------------------------------------------*/
153 /*----------------------------------------------------------------------------*/
154 
157 /*-----------------------------------------------------------------------------
158  Function codes
159  -----------------------------------------------------------------------------*/
160 
161 /*----------------------------------------------------------------------------*/
169 /*----------------------------------------------------------------------------*/
170 irplib_framelist * irplib_framelist_new(void)
171 {
172 
173  return (irplib_framelist *) cpl_calloc(1, sizeof(irplib_framelist));
174 
175 }
176 
177 /*----------------------------------------------------------------------------*/
182 /*----------------------------------------------------------------------------*/
183 void irplib_framelist_delete(irplib_framelist * self)
184 {
185 
187  cpl_free(self);
188 }
189 
190 
191 /*----------------------------------------------------------------------------*/
200 /*----------------------------------------------------------------------------*/
201 irplib_framelist * irplib_framelist_cast(const cpl_frameset * frameset)
202 {
203 
204  irplib_framelist * self;
205  const cpl_frame * frame;
206  int i;
207 
208 
209  cpl_ensure(frameset != NULL, CPL_ERROR_NULL_INPUT, NULL);
210 
211  /* The function cannot fail now */
212  self = irplib_framelist_new();
213 
214  for (i = 0; i < cpl_frameset_get_size(frameset); i++)
215  {
216  frame = cpl_frameset_get_position_const(frameset, i);
217 
218  cpl_frame * copy = cpl_frame_duplicate(frame);
219 
220  const cpl_error_code error = irplib_framelist_set(self, copy, i);
221 
222  assert(error == CPL_ERROR_NONE);
223 
224  }
225 
226  assert(self->size == cpl_frameset_get_size(frameset));
227 
228  return self;
229 
230 }
231 
232 
233 /*----------------------------------------------------------------------------*/
242 /*----------------------------------------------------------------------------*/
243 cpl_frameset * irplib_frameset_cast(const irplib_framelist * self)
244 {
245 
246  cpl_frameset * new;
247  int i;
248 
249  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
250 
251  /* The function cannot fail now */
252  new = cpl_frameset_new();
253 
254  for (i = 0; i < self->size; i++) {
255  cpl_frame * frame = cpl_frame_duplicate(self->frame[i]);
256  const cpl_error_code error = cpl_frameset_insert(new, frame);
257 
258  assert(error == CPL_ERROR_NONE);
259 
260  }
261 
262  assert(self->size == cpl_frameset_get_size(new));
263 
264  return new;
265 
266 }
267 
268 
269 /*----------------------------------------------------------------------------*/
281 /*----------------------------------------------------------------------------*/
282 irplib_framelist * irplib_framelist_extract(const irplib_framelist * self,
283  const char * tag)
284 {
285 
286  irplib_framelist * new;
287  int i, newsize;
288 
289 
290  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
291  cpl_ensure(tag != NULL, CPL_ERROR_NULL_INPUT, NULL);
292 
293  new = irplib_framelist_new();
294  newsize = 0;
295 
296  for (i = 0; i < self->size; i++) {
297  const cpl_frame * frame = self->frame[i];
298  const char * ftag = cpl_frame_get_tag(frame);
299  cpl_frame * copy;
300  cpl_error_code error;
301 
302  if (ftag == NULL) {
303  /* The frame is ill-formed */
305  cpl_ensure(0, CPL_ERROR_ILLEGAL_INPUT, NULL);
306  }
307 
308  if (strcmp(tag, ftag)) continue;
309 
310  copy = cpl_frame_duplicate(frame);
311 
312  error = irplib_framelist_set(new, copy, newsize);
313  assert(error == CPL_ERROR_NONE);
314 
315  if (self->propertylist[i] != NULL) new->propertylist[newsize]
316  = cpl_propertylist_duplicate(self->propertylist[i]);
317 
318  newsize++;
319  }
320 
321  assert( newsize == new->size );
322 
323  if (newsize == 0) {
324 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
325  cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
326  "The list of %d frame(s) has no frames "
327  "with tag: %s", self->size, tag);
328 #else
329  cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
330  "The list of frame(s) has no frames "
331  "with the given tag");
332 #endif
334  new = NULL;
335  }
336 
337  return new;
338 
339 }
340 
341 /*----------------------------------------------------------------------------*/
351 /*----------------------------------------------------------------------------*/
352 irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist* self,
353  const char * regexp,
354  cpl_boolean invert)
355 {
356 
357  irplib_framelist * new;
358  int error;
359  int i, newsize;
360  const int xor = invert == CPL_FALSE ? 0 : 1;
361  regex_t re;
362 
363 
364  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
365  cpl_ensure(regexp != NULL, CPL_ERROR_NULL_INPUT, NULL);
366 
367  error = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
368  cpl_ensure(!error, CPL_ERROR_ILLEGAL_INPUT, NULL);
369 
370  new = irplib_framelist_new();
371  newsize = 0;
372 
373  for (i = 0; i < self->size; i++) {
374  const cpl_frame * frame = self->frame[i];
375  const char * tag = cpl_frame_get_tag(frame);
376  cpl_frame * copy;
377 
378  if (tag == NULL) {
379  /* The frame is ill-formed */
381  regfree(&re);
382  cpl_ensure(0, CPL_ERROR_ILLEGAL_INPUT, NULL);
383  }
384 
385  if ((regexec(&re, tag, (size_t)0, NULL, 0) == REG_NOMATCH ? 1 : 0)
386  ^ xor) continue;
387 
388  copy = cpl_frame_duplicate(frame);
389 
390  error = (int)irplib_framelist_set(new, copy, newsize);
391  assert(error == CPL_ERROR_NONE);
392 
393  if (self->propertylist[i] != NULL) new->propertylist[newsize]
394  = cpl_propertylist_duplicate(self->propertylist[i]);
395 
396  newsize++;
397 
398  }
399 
400  regfree(&re);
401 
402  assert( newsize == new->size );
403 
404  if (newsize == 0) {
405 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
406  cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
407  "The list of %d frame(s) has no frames "
408  "that match: %s", self->size, regexp);
409 #else
410  cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
411  "The list of frames has no frames "
412  "that match the regular expression");
413 #endif
415  new = NULL;
416  }
417 
418  return new;
419 }
420 
421 
422 /*----------------------------------------------------------------------------*/
429 /*----------------------------------------------------------------------------*/
430 int irplib_framelist_get_size(const irplib_framelist * self)
431 {
432 
433  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, -1);
434 
435  return self->size;
436 
437 }
438 
439 /*----------------------------------------------------------------------------*/
447 /*----------------------------------------------------------------------------*/
448 cpl_frame * irplib_framelist_get(irplib_framelist * self, int pos)
449 {
450  IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
451  return (cpl_frame *)irplib_framelist_get_const(self, pos);
452  IRPLIB_DIAG_PRAGMA_POP;
453 }
454 
455 
456 /*----------------------------------------------------------------------------*/
464 /*----------------------------------------------------------------------------*/
465 const cpl_frame * irplib_framelist_get_const(const irplib_framelist * self,
466  int pos)
467 {
468 
469  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
470  cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
471  cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
472 
473  return self->frame[pos];
474 
475 }
476 
477 
478 /*----------------------------------------------------------------------------*/
487 /*----------------------------------------------------------------------------*/
488 cpl_error_code irplib_framelist_set_propertylist(irplib_framelist * self,
489  int pos,
490  const cpl_propertylist * list)
491 {
492 
493  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
494  cpl_ensure_code(list != NULL, CPL_ERROR_NULL_INPUT);
495  cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
496  cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
497 
498  cpl_propertylist_delete(self->propertylist[pos]);
499 
500  self->propertylist[pos] = cpl_propertylist_duplicate(list);
501 
502  cpl_ensure_code(self->propertylist[pos] != NULL, cpl_error_get_code());
503 
504  return CPL_ERROR_NONE;
505 
506 }
507 
508 
509 /*----------------------------------------------------------------------------*/
520 /*----------------------------------------------------------------------------*/
521 cpl_propertylist * irplib_framelist_get_propertylist(irplib_framelist * self,
522  int pos)
523 {
524 
525  IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
526  return (cpl_propertylist *)irplib_framelist_get_propertylist_const(self,
527  pos);
528  IRPLIB_DIAG_PRAGMA_POP;
529 }
530 
531 
532 /*----------------------------------------------------------------------------*/
543 /*----------------------------------------------------------------------------*/
545  const irplib_framelist * self,
546  int pos)
547 {
548  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
549  cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
550  cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
551 
552  cpl_ensure(self->propertylist[pos] != NULL,
553  CPL_ERROR_DATA_NOT_FOUND, NULL);
554 
555  return self->propertylist[pos];
556 
557 }
558 
559 
560 /*----------------------------------------------------------------------------*/
574 /*----------------------------------------------------------------------------*/
575 cpl_error_code irplib_framelist_load_propertylist(irplib_framelist * self,
576  int pos, int ind,
577  const char * regexp,
578  cpl_boolean invert)
579 {
580 
581  const char * filename;
582 
583 
584  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
585  cpl_ensure_code(regexp != NULL, CPL_ERROR_NULL_INPUT);
586  cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
587  cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
588 
589  filename = cpl_frame_get_filename(self->frame[pos]);
590 
591  cpl_ensure_code(filename != NULL, cpl_error_get_code());
592 
593  cpl_propertylist_delete(self->propertylist[pos]);
594 
595  self->propertylist[pos] = cpl_propertylist_load_regexp(filename, ind,
596  regexp,
597  invert ? 1 : 0);
598 
599  if (self->propertylist[pos] == NULL) {
600 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
601  return cpl_error_set_message(cpl_func, cpl_error_get_code(), "Could "
602  "not load FITS header from '%s' using "
603  "regexp '%s'", filename, regexp);
604 #else
605  return cpl_error_set_message(cpl_func, cpl_error_get_code(),
606  "Could not load FITS header");
607 #endif
608  }
609 
610  return CPL_ERROR_NONE;
611 
612 }
613 
614 
615 /*----------------------------------------------------------------------------*/
629 /*----------------------------------------------------------------------------*/
630 cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist * self,
631  int ind,
632  const char * regexp,
633  cpl_boolean invert)
634 {
635 
636  int nprops = 0;
637  int nfiles = 0;
638  int i;
639 
640  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
641  cpl_ensure_code(regexp != NULL, CPL_ERROR_NULL_INPUT);
642 
643  for (i=0; i < self->size; i++) {
644  if (self->propertylist[i] == NULL)
645  cpl_ensure_code(!irplib_framelist_load_propertylist(self, i,
646  ind,
647  regexp,
648  invert),
649  cpl_error_get_code());
650  /* Counting just for diagnostics - this actually causes
651  the whole list to be reiterated :-( */
652  nprops += cpl_propertylist_get_size(self->propertylist[i]);
653  nfiles++;
654  }
655 
656  cpl_msg_info(cpl_func, "List of %d frames has %d properties", nfiles,
657  nprops);
658 
659  return CPL_ERROR_NONE;
660 
661 }
662 
663 
664 
665 /*----------------------------------------------------------------------------*/
673 /*----------------------------------------------------------------------------*/
674 cpl_error_code irplib_framelist_set_tag_all(irplib_framelist * self,
675  const char * tag)
676 {
677 
678  int i;
679 
680  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
681  cpl_ensure_code(tag != NULL, CPL_ERROR_NULL_INPUT);
682 
683  for (i=0; i < self->size; i++)
684  cpl_ensure_code(!cpl_frame_set_tag(self->frame[i], tag),
685  cpl_error_get_code());
686 
687  return CPL_ERROR_NONE;
688 }
689 
690 
691 /*----------------------------------------------------------------------------*/
705 /*----------------------------------------------------------------------------*/
706 cpl_error_code irplib_framelist_set(irplib_framelist * self, cpl_frame * frame,
707  int pos)
708 {
709 
710  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
711  cpl_ensure_code(frame != NULL, CPL_ERROR_NULL_INPUT);
712  cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
713 
714  if (pos == self->size) {
715 
716  self->size++;
717 
718  irplib_framelist_set_size(self);
719 
720  } else {
721 
722  cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
723 
724  cpl_frame_delete(self->frame[pos]);
725  cpl_propertylist_delete(self->propertylist[pos]);
726  }
727 
728  self->frame[pos] = frame;
729  self->propertylist[pos] = NULL;
730 
731  return CPL_ERROR_NONE;
732 
733 }
734 
735 /*----------------------------------------------------------------------------*/
744 /*----------------------------------------------------------------------------*/
745 cpl_error_code irplib_framelist_erase(irplib_framelist * self, int pos)
746 {
747 
748  int i;
749 
750  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
751  cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
752  cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
753 
754 
755  /* Delete the specified frame and its propertylist */
756  cpl_frame_delete(self->frame[pos]);
757  cpl_propertylist_delete(self->propertylist[pos]);
758 
759  /* Move following frames down one position */
760  for (i = pos+1; i < self->size; i++) {
761 
762  self->frame[i-1] = self->frame[i];
763 
764  self->propertylist[i-1] = self->propertylist[i];
765 
766  }
767 
768  self->size--;
769 
770  irplib_framelist_set_size(self);
771 
772  return CPL_ERROR_NONE;
773 
774 }
775 
776 
777 
778 /*----------------------------------------------------------------------------*/
794 /*----------------------------------------------------------------------------*/
795 cpl_frame * irplib_framelist_unset(irplib_framelist * self, int pos,
796  cpl_propertylist ** plist)
797 
798 {
799  cpl_frame * frame;
800  int i;
801 
802 
803  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
804  cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
805  cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
806 
807  /* Get the specified frame and its propertylist */
808  frame = self->frame[pos];
809 
810  if (plist != NULL)
811  *plist = self->propertylist[pos];
812  else
813  cpl_propertylist_delete(self->propertylist[pos]);
814 
815 
816  /* Move following frames down one position */
817  for (i = pos+1; i < self->size; i++) {
818 
819  self->frame[i-1] = self->frame[i];
820 
821  self->propertylist[i-1] = self->propertylist[i];
822 
823  }
824 
825  self->size--;
826 
827  irplib_framelist_set_size(self);
828 
829  return frame;
830 
831 }
832 
833 /*----------------------------------------------------------------------------*/
840 /*----------------------------------------------------------------------------*/
841 void irplib_framelist_empty(irplib_framelist * self)
842 {
843 
844  if (self != NULL) {
845 
846  /* Deallocate all frames and their propertylists */
847  while (self->size > 0) {
848  self->size--;
849  cpl_frame_delete(self->frame[self->size]);
850  cpl_propertylist_delete(self->propertylist[self->size]);
851 
852  }
853 
854  /* Deallocate the arrays */
855  irplib_framelist_set_size(self);
856 
857  }
858 }
859 
860 
861 
862 /*----------------------------------------------------------------------------*/
900 /*----------------------------------------------------------------------------*/
901 cpl_error_code irplib_framelist_contains(const irplib_framelist * self,
902  const char * key, cpl_type type,
903  cpl_boolean is_equal, double fp_tol)
904 {
905 
906  char * value_0;
907  char * value_i;
908  cpl_type type_0 = CPL_TYPE_INVALID;
909  int i, ifirst = -1; /* First non-NULL propertylist */
910 
911 
912  cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
913  cpl_ensure_code(key != NULL, CPL_ERROR_NULL_INPUT);
914  cpl_ensure_code(fp_tol >= 0.0, CPL_ERROR_ILLEGAL_INPUT);
915 
916  for (i=0; i < self->size; i++) {
917  cpl_type type_i;
918 
919 
920  if (self->propertylist[i] == NULL) continue;
921  if (ifirst < 0) ifirst = i;
922 
923  type_i = cpl_propertylist_get_type(self->propertylist[i], key);
924 
925  if (type_i == CPL_TYPE_INVALID) {
926  if (type == CPL_TYPE_INVALID)
927 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
928  cpl_error_set_message(cpl_func, cpl_error_get_code(), "FITS "
929  "key '%s' is missing from file %s", key,
930  cpl_frame_get_filename(self->frame[i]));
931  else
932  cpl_error_set_message(cpl_func, cpl_error_get_code(),
933  "FITS key '%s' [%s] is missing from file "
934  "%s", key, cpl_type_get_name(type),
935  cpl_frame_get_filename(self->frame[i]));
936 #else
937  cpl_error_set_message(cpl_func, cpl_error_get_code(),
938  "A FITS key is missing from a file");
939  else
940  cpl_error_set_message(cpl_func, cpl_error_get_code(),
941  "A FITS key is missing from a file");
942 #endif
943  return cpl_error_get_code();
944  }
945 
946  if (type != CPL_TYPE_INVALID && type_i != type) {
947 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
948  return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
949  "FITS key '%s' has type %s instead of "
950  "%s in file %s", key,
951  cpl_type_get_name(type_i),
952  cpl_type_get_name(type),
953  cpl_frame_get_filename(self->frame[i]));
954 #else
955  return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
956  "A FITS key had an unexpected type");
957 #endif
958 
959  }
960 
961  if (!is_equal) continue;
962 
963  if (type_0 == CPL_TYPE_INVALID) {
964  type_0 = type_i;
965  continue;
966  }
967 
968  if (type_i != type_0) {
969  assert( type == CPL_TYPE_INVALID );
970 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
971  return cpl_error_set_message(cpl_func, CPL_ERROR_TYPE_MISMATCH,
972  "FITS key '%s' has different types "
973  "(%s <=> %s) in files %s and %s", key,
974  cpl_type_get_name(type_0),
975  cpl_type_get_name(type_i),
976  cpl_frame_get_filename(self->frame[0]),
977  cpl_frame_get_filename(self->frame[i]));
978 #else
979  return cpl_error_set_message(cpl_func, CPL_ERROR_TYPE_MISMATCH,
980  "A FITS key has different types in "
981  "two files");
982 #endif
983  }
984 
985  if (irplib_property_equal(self->propertylist[ifirst],
986  self->propertylist[i],
987  key, type_0, fp_tol, &value_0, &value_i))
988  continue;
989 
990  if ((type_0 == CPL_TYPE_FLOAT || type_0 == CPL_TYPE_DOUBLE)
991  && fp_tol > 0.0) {
992 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
993  cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT, "FITS"
994  " key '%s' [%s] has values that differ by "
995  "more than %g (%s <=> %s) in files %s and %s",
996  key, cpl_type_get_name(type_0), fp_tol,
997  value_0, value_i,
998  cpl_frame_get_filename(self->frame[0]),
999  cpl_frame_get_filename(self->frame[i]));
1000 #else
1001  cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT, "A "
1002  "FITS key has values that differ by more "
1003  "than the allowed tolerance in two file");
1004 #endif
1005  } else {
1006 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1007  cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1008  "FITS key '%s' [%s] has different values "
1009  "(%s <=> %s) in files %s and %s", key,
1010  cpl_type_get_name(type_0),
1011  value_0, value_i,
1012  cpl_frame_get_filename(self->frame[0]),
1013  cpl_frame_get_filename(self->frame[i]));
1014 #else
1015  cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT, "A "
1016  "FITS key has different values in two files");
1017 #endif
1018  }
1019  cpl_free(value_0);
1020  cpl_free(value_i);
1021 
1022  return cpl_error_get_code();
1023  }
1024 
1025  return CPL_ERROR_NONE;
1026 
1027 }
1028 
1029 
1030 /*----------------------------------------------------------------------------*/
1043 /*----------------------------------------------------------------------------*/
1044 cpl_imagelist * irplib_imagelist_load_framelist(const irplib_framelist * self,
1045  cpl_type pixeltype,
1046  int planenum,
1047  int extnum)
1048 {
1049 
1050  cpl_imagelist * list = NULL;
1051  cpl_image * image = NULL;
1052  int i;
1053 
1054 
1055  cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1056  cpl_ensure(extnum >= 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1057  cpl_ensure(planenum >= 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1058 
1059  list = cpl_imagelist_new();
1060 
1061  for (i=0; i < self->size; i++, image = NULL) {
1062  const char * filename = cpl_frame_get_filename(self->frame[i]);
1063  cpl_error_code error;
1064 
1065  if (filename == NULL) break;
1066 
1067  image = cpl_image_load(filename, pixeltype, planenum, extnum);
1068  if (image == NULL) {
1069 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1070  (void)cpl_error_set_message(cpl_func, cpl_error_get_code(),
1071  "Could not load FITS-image from plane "
1072  "%d in extension %d in file %s",
1073  planenum, extnum, filename);
1074 #else
1075  (void)cpl_error_set_message(cpl_func, cpl_error_get_code(),
1076  "Could not load FITS-image");
1077 #endif
1078  break;
1079  }
1080 
1081  error = cpl_imagelist_set(list, image, i);
1082  assert(error == CPL_ERROR_NONE);
1083  }
1084 
1085  cpl_image_delete(image);
1086 
1087  if (cpl_imagelist_get_size(list) != self->size) {
1088  cpl_imagelist_delete(list);
1089  list = NULL;
1090  assert(cpl_error_get_code() != CPL_ERROR_NONE);
1091  }
1092 
1093  return list;
1094 
1095 }
1096 
1097 
1101 /*----------------------------------------------------------------------------*/
1113 /*----------------------------------------------------------------------------*/
1114 static void irplib_framelist_set_size(irplib_framelist * self)
1115 {
1116 
1117 
1118  assert( self != NULL);
1119 
1120  if (self->size == 0) {
1121  /* The list has been emptied */
1122  cpl_free(self->frame);
1123  cpl_free(self->propertylist);
1124  self->frame = NULL;
1125  self->propertylist = NULL;
1126  } else {
1127  /* Update the size of the arrays */
1128 
1129  self->frame = cpl_realloc(self->frame, self->size * sizeof(cpl_frame*));
1130  self->propertylist =
1131  cpl_realloc(self->propertylist,
1132  self->size * sizeof(cpl_propertylist*));
1133  }
1134 
1135 }
1136 
1137 /*----------------------------------------------------------------------------*/
1161 /*----------------------------------------------------------------------------*/
1162 static cpl_boolean irplib_property_equal(const cpl_propertylist * self,
1163  const cpl_propertylist * other,
1164  const char * key, cpl_type type,
1165  double fp_tol,
1166  char ** sstring, char ** ostring)
1167 {
1168 
1169  cpl_boolean equal;
1170 
1171 
1172  assert(self != NULL);
1173  assert(other != NULL);
1174  assert(key != NULL);
1175  assert(sstring != NULL);
1176  assert(ostring != NULL);
1177 
1178  /* FIXME: disable for better performance also with debugging */
1179  assert(cpl_propertylist_get_type(other, key) == type);
1180  assert(fp_tol >= 0.0);
1181 
1182  if (self == other) return CPL_TRUE;
1183 
1184  switch (type) {
1185 
1186  case CPL_TYPE_CHAR: {
1187  const char svalue = cpl_propertylist_get_char(self, key);
1188  const char ovalue = cpl_propertylist_get_char(other, key);
1189 
1190  equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1191  if (!equal) {
1192  *sstring = cpl_sprintf("%c", svalue);
1193  *ostring = cpl_sprintf("%c", ovalue);
1194  }
1195  break;
1196  }
1197 
1198  case CPL_TYPE_BOOL: {
1199  const int svalue = cpl_propertylist_get_bool(self, key);
1200  const int ovalue = cpl_propertylist_get_bool(other, key);
1201 
1202  equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1203  if (!equal) {
1204  *sstring = cpl_strdup(svalue == 0 ? "F" : "T");
1205  *ostring = cpl_strdup(ovalue == 0 ? "F" : "T");
1206  }
1207  break;
1208  }
1209 
1210  case CPL_TYPE_INT: {
1211  const int svalue = cpl_propertylist_get_int(self, key);
1212  const int ovalue = cpl_propertylist_get_int(other, key);
1213 
1214  equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1215  if (!equal) {
1216  *sstring = cpl_sprintf("%d", svalue);
1217  *ostring = cpl_sprintf("%d", ovalue);
1218  }
1219  break;
1220  }
1221 
1222  case CPL_TYPE_LONG: {
1223  const long svalue = cpl_propertylist_get_long(self, key);
1224  const long ovalue = cpl_propertylist_get_long(other, key);
1225 
1226  equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1227  if (!equal) {
1228  *sstring = cpl_sprintf("%ld", svalue);
1229  *ostring = cpl_sprintf("%ld", ovalue);
1230  }
1231  break;
1232  }
1233 
1234  case CPL_TYPE_FLOAT: {
1235  const double svalue = (double)cpl_propertylist_get_float(self, key);
1236  const double ovalue = (double)cpl_propertylist_get_float(other, key);
1237 
1238  equal = (fabs(svalue - ovalue) <= fp_tol) ? CPL_TRUE : CPL_FALSE;
1239  if (!equal) {
1240  *sstring = cpl_sprintf("%f", svalue);
1241  *ostring = cpl_sprintf("%f", ovalue);
1242  }
1243  break;
1244  }
1245 
1246  case CPL_TYPE_DOUBLE: {
1247  const double svalue = cpl_propertylist_get_double(self, key);
1248  const double ovalue = cpl_propertylist_get_double(other, key);
1249 
1250  equal = (fabs(svalue - ovalue) <= fp_tol) ? CPL_TRUE : CPL_FALSE;
1251  if (!equal) {
1252  *sstring = cpl_sprintf("%g", svalue);
1253  *ostring = cpl_sprintf("%g", ovalue);
1254  }
1255  break;
1256  }
1257  case CPL_TYPE_STRING: {
1258  const char * svalue = cpl_propertylist_get_string(self, key);
1259  const char * ovalue = cpl_propertylist_get_string(other, key);
1260 
1261  equal = strcmp(svalue, ovalue) == 0 ? CPL_TRUE : CPL_FALSE;
1262  if (!equal) {
1263  *sstring = cpl_strdup(svalue);
1264  *ostring = cpl_strdup(ovalue);
1265  }
1266  break;
1267  }
1268  default:
1269  /* Unknown property type */
1270  assert( 0 );
1271 
1272  equal = CPL_FALSE; /* In case of -DNDEBUG */
1273 
1274  }
1275 
1276  if (!equal) {
1277  assert( *sstring != NULL );
1278  assert( *ostring != NULL );
1279  }
1280 
1281  return equal;
1282 
1283 }