GIRAFFE Pipeline Reference Manual

gipaf.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2006 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
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  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author$
23  * $Date$
24  * $Revision$
25  * $Name$
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <pwd.h>
35 #if defined HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38 
39 #include <cxmemory.h>
40 #include <cxstring.h>
41 #include <cxstrutils.h>
42 
43 #include <cpl_propertylist.h>
44 
45 #include "giutils.h"
46 #include "gipaf.h"
47 
48 
49 #define PAF_HDR_START "PAF.HDR.START"
50 #define PAF_TYPE "PAF.TYPE"
51 #define PAF_ID "PAF.ID"
52 #define PAF_NAME "PAF.NAME"
53 #define PAF_DESC "PAF.DESC"
54 #define PAF_CRTE_NAME "PAF.CRTE.NAME"
55 #define PAF_CRTE_TIME "PAF.CRTE.DAYTIM"
56 #define PAF_LCHG_NAME "PAF.LCHG.NAME"
57 #define PAF_LCHG_TIME "PAF.LCHG.DAYTIM"
58 #define PAF_CHCK_NAME "PAF.CHCK.NAME"
59 #define PAF_CHCK_TIME "PAF.CHCK.DAYTIM"
60 #define PAF_CHCK_CHECKSUM "PAF.CHCK.CHECKSUM"
61 #define PAF_HDR_END "PAF.HDR.END"
62 
63 
64 /*
65  * Value and comment field start position
66  */
67 
68 static const cxsize PAF_FIELD_OFFSET_VALUE = 20;
69 static const cxsize PAF_FIELD_OFFSET_COMMENT = 45;
70 
71 
72 /*
73  * Maximum length of a parameter file record, i.e. maximum number of
74  * characters per line of a parameter file on disk. This does not include
75  * a trailing 0.
76  */
77 
78 static const cxsize PAF_RECORD_MAX = 256;
79 
80 
89 struct GiPafHdr {
90  cxchar *name;
91  cxchar *type;
92  cxchar *id;
93  cxchar *description;
94 };
95 
96 typedef struct GiPafHdr GiPafHdr;
97 
98 
99 struct GiPaf {
100  GiPafHdr *header;
101  cpl_propertylist *records;
102 };
103 
104 
105 inline static cxint
106 _giraffe_paf_format_line(cx_string *line, const cxchar *name,
107  const cxchar *value, const cxchar *comment,
108  cxbool append)
109 {
110 
111  cxchar buffer[PAF_RECORD_MAX + 2];
112 
113  cxsize sz = 0;
114  cxsize cpos = 0;
115 
116 
117  cx_assert(line != NULL);
118 
119  if (name == NULL) {
120  return -1;
121  }
122 
123 
124  /*
125  * Verify that the record name fits into the buffer. The extra
126  * character is for the semicolon which has to be present.
127  */
128 
129  sz = strlen(name);
130 
131  if (sz + 1 > PAF_RECORD_MAX) {
132  return 1;
133  }
134 
135  memset(buffer, ' ', PAF_RECORD_MAX + 1);
136  memcpy(buffer, name, sz);
137 
138  cpos = sz;
139 
140  if (value != NULL) {
141 
142  if (cpos < PAF_FIELD_OFFSET_VALUE) {
143  cpos = PAF_FIELD_OFFSET_VALUE;
144  }
145  else {
146  ++cpos;
147  }
148 
149  sz = strlen(value);
150 
151 
152  /*
153  * Verify that writing the value string does not overflow
154  * the buffer.
155  */
156 
157  if (sz > PAF_RECORD_MAX - cpos + 1) {
158  return 2;
159  }
160 
161  memcpy(&buffer[cpos], value, sz);
162  cpos += sz;
163 
164  }
165 
166  buffer[cpos++] = ';';
167 
168 
169  /*
170  * Comments are only printed if there is room in the buffer for
171  * at least 3 characters, so that not only the hash and the
172  * following blank appear in the output because of the finite
173  * record size.
174  */
175 
176  if (comment != NULL && comment[0] != '\0' &&
177  (PAF_RECORD_MAX - cpos + 1) > 2) {
178 
179  if (cpos < PAF_FIELD_OFFSET_COMMENT) {
180  cpos = PAF_FIELD_OFFSET_COMMENT;
181  }
182  else {
183  ++cpos;
184  }
185 
186  memcpy(&buffer[cpos], "# ", 2);
187  cpos += 2;
188 
189  sz = strlen(comment);
190  sz = sz < PAF_RECORD_MAX - cpos + 1 ? sz : PAF_RECORD_MAX - cpos + 1;
191 
192  memcpy(&buffer[cpos], comment, sz);
193  cpos += sz;
194  }
195 
196  buffer[cpos] = '\n';
197  buffer[++cpos] = '\0';
198 
199 
200  if (append == TRUE) {
201  cx_string_append(line, buffer);
202  }
203  else {
204  cx_string_set(line, buffer);
205  }
206 
207  return 0;
208 
209 }
210 
211 
212 inline static cxint
213 _giraffe_paf_convert_property(cx_string *line, cpl_property *property,
214  cxbool append)
215 {
216 
217  cxint status = 0;
218 
219  const cxchar *name;
220  const cxchar *comment;
221 
222  cx_string *value = NULL;
223 
224 
225  cx_assert(line != NULL);
226 
227  if (property == NULL) {
228  return -1;
229  }
230 
231  value = cx_string_new();
232 
233  switch (cpl_property_get_type(property)) {
234  case CPL_TYPE_CHAR:
235  {
236  cxchar c = cpl_property_get_char(property);
237 
238  cx_string_sprintf(value, "%c", c);
239  }
240  break;
241 
242  case CPL_TYPE_BOOL:
243  {
244  cxint b = cpl_property_get_bool(property);
245 
246  if (b != 0) {
247  cx_string_set(value, "T");
248  }
249  else {
250  cx_string_set(value, "F");
251  }
252  }
253  break;
254 
255  case CPL_TYPE_INT:
256  {
257  cxint i = cpl_property_get_int(property);
258 
259  cx_string_sprintf(value, "%d", i);
260  }
261  break;
262 
263  case CPL_TYPE_LONG:
264  {
265  cxlong l = cpl_property_get_long(property);
266 
267  cx_string_sprintf(value, "%ld", l);
268  }
269  break;
270 
271  case CPL_TYPE_FLOAT:
272  {
273  cxfloat f = cpl_property_get_float(property);
274 
275  cx_string_sprintf(value, "%.15G", f);
276 
277  if (!strchr(cx_string_get(value), '.')) {
278 
279  if (strchr(cx_string_get(value), 'E')) {
280  cx_string_sprintf(value, "%.1E", f);
281  }
282  else {
283  cx_string_append(value, ".");
284  }
285  }
286  }
287  break;
288 
289  case CPL_TYPE_DOUBLE:
290  {
291  cxdouble d = cpl_property_get_double(property);
292 
293  cx_string_sprintf(value, "%.15G", d);
294 
295  if (!strchr(cx_string_get(value), '.')) {
296 
297  if (strchr(cx_string_get(value), 'E')) {
298  cx_string_sprintf(value, "%.1E", d);
299  }
300  else {
301  cx_string_append(value, ".");
302  }
303  }
304  }
305  break;
306 
307  case CPL_TYPE_STRING:
308  {
309  const cxchar *s = cpl_property_get_string(property);
310 
311  cx_string_sprintf(value, "\"%s\"", s);
312  }
313  break;
314 
315  default:
316 
317  /*
318  * Unsupported property type. This point should never be
319  * reached!
320  */
321 
322  cx_string_delete(value);
323 
324  return 1;
325  break;
326  }
327 
328  name = cpl_property_get_name(property);
329  comment = cpl_property_get_comment(property);
330 
331  status = _giraffe_paf_format_line(line, name, cx_string_get(value),
332  comment, append);
333 
334  if (status != 0) {
335  cx_string_delete(value);
336  return 2;
337  }
338 
339  cx_string_delete(value);
340 
341  return 0;
342 
343 }
344 
345 
346 inline static GiPafHdr *
347 _giraffe_pafhdr_create(const cxchar *name, const cxchar *type,
348  const cxchar *id, const cxchar *description)
349 {
350 
351  GiPafHdr *self = cx_calloc(1, sizeof *self);
352 
353 
354  self->name = cx_strdup(name);
355  self->type = cx_strdup(type);
356 
357  if (id != NULL) {
358  self->id = cx_strdup(id);
359  }
360 
361  if (description != NULL) {
362  self->description = cx_strdup(description);
363  }
364 
365  return self;
366 
367 }
368 
369 
370 inline static void
371 _giraffe_pafhdr_destroy(GiPafHdr *self)
372 {
373 
374  if (self != NULL) {
375  if (self->name != NULL) {
376  cx_free(self->name);
377  self->name = NULL;
378  }
379 
380  if (self->type != NULL) {
381  cx_free(self->type);
382  self->type = NULL;
383  }
384 
385  if (self->id != NULL) {
386  cx_free(self->id);
387  self->id = NULL;
388  }
389 
390  if (self->description != NULL) {
391  cx_free(self->description);
392  self->description = NULL;
393  }
394 
395  cx_free(self);
396  }
397 
398  return;
399 
400 }
401 
402 
403 inline static cxint
404 _giraffe_pafhdr_write(GiPafHdr *self, FILE *stream)
405 {
406 
407  if (stream == NULL) {
408  return -1;
409  }
410 
411  if (self != NULL) {
412 
413  cxchar *user;
414  cxchar *timestamp;
415 
416  cx_string *header = cx_string_new();
417 
418 
419 #if defined HAVE_GETUID && defined HAVE_GETPWUID
420 
421  struct passwd *pw;
422 
423  pw = getpwuid(getuid());
424 
425  if (pw == NULL) {
426  cx_string_delete(header);
427  return 1;
428  }
429 
430  user = pw->pw_name;
431 
432 #else
433  user = getenv("USER");
434  user = user == NULL ? getenv("LOGNAME") : user;
435 
436  if (user == NULL) {
437  cx_string_delete(header);
438  return 1;
439  }
440 
441 #endif
442 
443  timestamp = giraffe_localtime_iso8601();
444 
445  if (timestamp == NULL) {
446  cx_string_delete(header);
447  return 2;
448  }
449 
450 
451  /*
452  * Write formatted header records to a string buffer
453  */
454 
455  _giraffe_paf_format_line(header, PAF_HDR_START, NULL, NULL, TRUE);
456  _giraffe_paf_format_line(header, PAF_TYPE, self->type, "Type of "
457  "parameter file", TRUE);
458 
459  if (self->id != NULL) {
460  _giraffe_paf_format_line(header, PAF_ID, self->id, NULL, TRUE);
461  }
462  else {
463  _giraffe_paf_format_line(header, PAF_ID, "", NULL, TRUE);
464  }
465 
466  _giraffe_paf_format_line(header, PAF_NAME, self->name, "Name of "
467  "PAF", TRUE);
468 
469  if (self->description != NULL) {
470  _giraffe_paf_format_line(header, PAF_DESC, self->description,
471  "Short description of PAF", TRUE);
472  }
473  else {
474  _giraffe_paf_format_line(header, PAF_DESC, "", "Short "
475  "description of PAF", TRUE);
476  }
477 
478  _giraffe_paf_format_line(header, PAF_CRTE_NAME, user, "Name of "
479  "creator", TRUE);
480  _giraffe_paf_format_line(header, PAF_CRTE_TIME, timestamp,
481  "Civil time for creation", TRUE);
482 
483  _giraffe_paf_format_line(header, PAF_LCHG_NAME, "", "Author of "
484  "par. file", TRUE);
485  _giraffe_paf_format_line(header, PAF_LCHG_TIME, "", "Timestamp for "
486  "last change", TRUE);
487 
488  _giraffe_paf_format_line(header, PAF_CHCK_NAME, "", "Name of appl. "
489  "checking", TRUE);
490  _giraffe_paf_format_line(header, PAF_CHCK_TIME, "", "Time for "
491  "checking", TRUE);
492  _giraffe_paf_format_line(header, PAF_CHCK_CHECKSUM, "", "Checksum "
493  "for the PAF", TRUE);
494 
495  _giraffe_paf_format_line(header, PAF_HDR_END, NULL, NULL, TRUE);
496 
497 
498  /*
499  * Write string buffer contents to the output stream
500  */
501 
502  fprintf(stream, "%s", cx_string_get(header));
503 
504  if (ferror(stream) != 0) {
505  cx_free(timestamp);
506  cx_string_delete(header);
507 
508  return 3;
509  }
510 
511  cx_free(timestamp);
512  cx_string_delete(header);
513  }
514 
515  return 0;
516 
517 }
518 
519 
520 GiPaf *
521 giraffe_paf_new(const cxchar *name, const cxchar *type, const cxchar *id,
522  const cxchar *description)
523 {
524 
525  GiPaf *self = NULL;
526 
527 
528  if (name == NULL || type == NULL) {
529  return NULL;
530  }
531 
532  self = cx_malloc(sizeof *self);
533 
534  self->header = _giraffe_pafhdr_create(name, type, id, description);
535  self->records = cpl_propertylist_new();
536 
537  cx_assert(self->header != NULL);
538  cx_assert(self->records != NULL);
539 
540  return self;
541 
542 }
543 
544 
545 void
546 giraffe_paf_delete(GiPaf *self)
547 {
548 
549  if (self != NULL) {
550  if (self->records != NULL) {
551  cpl_propertylist_delete(self->records);
552  self->records = NULL;
553  }
554 
555  if (self->header != NULL) {
556  _giraffe_pafhdr_destroy(self->header);
557  self->header = NULL;
558  }
559 
560  cx_free(self);
561  }
562 
563  return;
564 
565 }
566 
567 
568 cxchar *
569 giraffe_paf_get_name(const GiPaf *self)
570 {
571 
572  if (self == NULL) {
573  return NULL;
574  }
575 
576  cx_assert(self->header != NULL);
577  cx_assert(self->header->name != NULL);
578 
579  return self->header->name;
580 
581 }
582 
583 
584 cxint
585 giraffe_paf_set_name(GiPaf *self, const cxchar *name)
586 {
587 
588  cx_assert(self != NULL);
589 
590  if (name == NULL) {
591  return -1;
592  }
593 
594  if (self->header->name != NULL) {
595  self->header->name = cx_realloc(self->header->name,
596  (strlen(name) + 1) * sizeof(cxchar));
597  strcpy(self->header->name, name);
598  }
599  else {
600  self->header->name = cx_strdup(name);
601  }
602 
603  return 0;
604 
605 }
606 
607 
608 cxchar *
609 giraffe_paf_get_type(const GiPaf *self)
610 {
611 
612  if (self == NULL) {
613  return NULL;
614  }
615 
616  cx_assert(self->header != NULL);
617  cx_assert(self->header->type != NULL);
618 
619  return self->header->type;
620 
621 }
622 
623 
624 cxint
625 giraffe_paf_set_type(GiPaf *self, const cxchar *type)
626 {
627 
628  cx_assert(self != NULL);
629 
630  if (type == NULL) {
631  return -1;
632  }
633 
634  if (self->header->type != NULL) {
635  self->header->type = cx_realloc(self->header->type,
636  (strlen(type) + 1) * sizeof(cxchar));
637  strcpy(self->header->type, type);
638  }
639  else {
640  self->header->type = cx_strdup(type);
641  }
642 
643  return 0;
644 
645 }
646 
647 
648 cxchar *
649 giraffe_paf_get_id(const GiPaf *self)
650 {
651 
652  if (self == NULL) {
653  return NULL;
654  }
655 
656  cx_assert(self->header != NULL);
657 
658  return self->header->id;
659 
660 }
661 
662 
663 cxint
664 giraffe_paf_set_id(GiPaf *self, const cxchar *id)
665 {
666 
667  cx_assert(self != NULL);
668 
669  if (id == NULL) {
670  return -1;
671  }
672 
673  if (self->header->id != NULL) {
674  self->header->id = cx_realloc(self->header->id,
675  (strlen(id) + 1) * sizeof(cxchar));
676  strcpy(self->header->id, id);
677  }
678  else {
679  self->header->id = cx_strdup(id);
680  }
681 
682  return 0;
683 
684 }
685 
686 
687 cxchar *
688 giraffe_paf_get_description(const GiPaf *self)
689 {
690 
691  if (self == NULL) {
692  return NULL;
693  }
694 
695  cx_assert(self->header != NULL);
696 
697  return self->header->description;
698 
699 }
700 
701 
702 cxint
703 giraffe_paf_set_description(GiPaf *self, const cxchar *description)
704 {
705 
706  cx_assert(self != NULL);
707 
708  if (description == NULL) {
709  return -1;
710  }
711 
712  if (self->header->description != NULL) {
713  self->header->description = cx_realloc(self->header->description,
714  (strlen(description) + 1) *
715  sizeof(cxchar));
716  strcpy(self->header->description, description);
717  }
718  else {
719  self->header->description = cx_strdup(description);
720  }
721 
722  return 0;
723 
724 }
725 
726 
727 cpl_propertylist *
728 giraffe_paf_get_properties(const GiPaf *self)
729 {
730 
731  if (self == NULL) {
732  return NULL;
733  }
734 
735  cx_assert(self->records != NULL);
736 
737  return self->records;
738 
739 }
740 
741 
742 cxint
743 giraffe_paf_set_properties(GiPaf *self, const cpl_propertylist *properties)
744 {
745 
746  cx_assert(self != NULL);
747 
748  if (properties == NULL) {
749  return -1;
750  }
751 
752  if (self->records != NULL) {
753  cpl_propertylist_delete(self->records);
754  }
755 
756  self->records = cpl_propertylist_duplicate(properties);
757 
758  return 0;
759 
760 }
761 
762 
763 cxint
764 giraffe_paf_write(const GiPaf *self)
765 {
766 
767  cxint status = 0;
768 
769  FILE *stream = NULL;
770 
771 
772  if (self == NULL) {
773  return -1;
774  }
775 
776  cx_assert(self->header != NULL);
777 
778  stream = fopen(giraffe_paf_get_name(self), "wb");
779 
780  if (stream == NULL) {
781  return 1;
782  }
783 
784 
785  /*
786  * Write PAF header
787  */
788 
789  status = _giraffe_pafhdr_write(self->header, stream);
790 
791  if (status != 0) {
792  fclose(stream);
793  return 2;
794  }
795 
796  fflush(stream);
797 
798 
799  /*
800  * Write PAF records
801  */
802 
803  if (self->records != NULL && !cpl_propertylist_is_empty(self->records)) {
804 
805  cxchar buffer[PAF_RECORD_MAX];
806 
807  register cxlong i;
808 
809  cx_string *line = NULL;
810 
811 
812  buffer[0] = '#';
813  memset(&buffer[1], '-', 78);
814  buffer[79] = '\0';
815  fprintf(stream, "%s\n", buffer);
816 
817  if (ferror(stream) != 0) {
818  fclose(stream);
819  return 3;
820  }
821 
822  line = cx_string_new();
823 
824  for (i = 0; i < cpl_propertylist_get_size(self->records); i++) {
825 
826  cpl_property *p = cpl_propertylist_get(self->records, i);
827 
828 
829  status = _giraffe_paf_convert_property(line, p, FALSE);
830 
831  if (status != 0) {
832  cx_string_delete(line);
833  fclose(stream);
834 
835  return 4;
836  }
837 
838  fprintf(stream, "%s", cx_string_get(line));
839 
840  if (ferror(stream) != 0) {
841  cx_string_delete(line);
842  fclose(stream);
843 
844  return 5;
845  }
846  }
847 
848  cx_string_delete(line);
849  fflush(stream);
850 
851  }
852 
853  fclose(stream);
854 
855  return 0;
856 
857 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:52 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004