35 #if defined HAVE_SYS_TYPES_H
36 # include <sys/types.h>
41 #include <cxstrutils.h>
43 #include <cpl_propertylist.h>
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"
68 static const cxsize PAF_FIELD_OFFSET_VALUE = 20;
69 static const cxsize PAF_FIELD_OFFSET_COMMENT = 45;
78 static const cxsize PAF_RECORD_MAX = 256;
96 typedef struct GiPafHdr GiPafHdr;
101 cpl_propertylist *records;
106 _giraffe_paf_format_line(cx_string *line,
const cxchar *name,
107 const cxchar *value,
const cxchar *comment,
111 cxchar buffer[PAF_RECORD_MAX + 2];
117 cx_assert(line != NULL);
131 if (sz + 1 > PAF_RECORD_MAX) {
135 memset(buffer,
' ', PAF_RECORD_MAX + 1);
136 memcpy(buffer, name, sz);
142 if (cpos < PAF_FIELD_OFFSET_VALUE) {
143 cpos = PAF_FIELD_OFFSET_VALUE;
157 if (sz > PAF_RECORD_MAX - cpos + 1) {
161 memcpy(&buffer[cpos], value, sz);
166 buffer[cpos++] =
';';
176 if (comment != NULL && comment[0] !=
'\0' &&
177 (PAF_RECORD_MAX - cpos + 1) > 2) {
179 if (cpos < PAF_FIELD_OFFSET_COMMENT) {
180 cpos = PAF_FIELD_OFFSET_COMMENT;
186 memcpy(&buffer[cpos],
"# ", 2);
189 sz = strlen(comment);
190 sz = sz < PAF_RECORD_MAX - cpos + 1 ? sz : PAF_RECORD_MAX - cpos + 1;
192 memcpy(&buffer[cpos], comment, sz);
197 buffer[++cpos] =
'\0';
200 if (append == TRUE) {
201 cx_string_append(line, buffer);
204 cx_string_set(line, buffer);
213 _giraffe_paf_convert_property(cx_string *line, cpl_property *property,
220 const cxchar *comment;
222 cx_string *value = NULL;
225 cx_assert(line != NULL);
227 if (property == NULL) {
231 value = cx_string_new();
233 switch (cpl_property_get_type(property)) {
236 cxchar c = cpl_property_get_char(property);
238 cx_string_sprintf(value,
"%c", c);
244 cxint b = cpl_property_get_bool(property);
247 cx_string_set(value,
"T");
250 cx_string_set(value,
"F");
257 cxint i = cpl_property_get_int(property);
259 cx_string_sprintf(value,
"%d", i);
265 cxlong l = cpl_property_get_long(property);
267 cx_string_sprintf(value,
"%ld", l);
273 cxfloat f = cpl_property_get_float(property);
275 cx_string_sprintf(value,
"%.15G", f);
277 if (!strchr(cx_string_get(value),
'.')) {
279 if (strchr(cx_string_get(value),
'E')) {
280 cx_string_sprintf(value,
"%.1E", f);
283 cx_string_append(value,
".");
289 case CPL_TYPE_DOUBLE:
291 cxdouble d = cpl_property_get_double(property);
293 cx_string_sprintf(value,
"%.15G", d);
295 if (!strchr(cx_string_get(value),
'.')) {
297 if (strchr(cx_string_get(value),
'E')) {
298 cx_string_sprintf(value,
"%.1E", d);
301 cx_string_append(value,
".");
307 case CPL_TYPE_STRING:
309 const cxchar *s = cpl_property_get_string(property);
311 cx_string_sprintf(value,
"\"%s\"", s);
322 cx_string_delete(value);
328 name = cpl_property_get_name(property);
329 comment = cpl_property_get_comment(property);
331 status = _giraffe_paf_format_line(line, name, cx_string_get(value),
335 cx_string_delete(value);
339 cx_string_delete(value);
346 inline static GiPafHdr *
347 _giraffe_pafhdr_create(
const cxchar *name,
const cxchar *type,
348 const cxchar *
id,
const cxchar *description)
351 GiPafHdr *
self = cx_calloc(1,
sizeof *
self);
354 self->name = cx_strdup(name);
355 self->type = cx_strdup(type);
358 self->id = cx_strdup(
id);
361 if (description != NULL) {
362 self->description = cx_strdup(description);
371 _giraffe_pafhdr_destroy(GiPafHdr *
self)
375 if (self->name != NULL) {
380 if (self->type != NULL) {
385 if (self->id != NULL) {
390 if (self->description != NULL) {
391 cx_free(self->description);
392 self->description = NULL;
404 _giraffe_pafhdr_write(GiPafHdr *
self, FILE *stream)
407 if (stream == NULL) {
416 cx_string *header = cx_string_new();
419 #if defined HAVE_GETUID && defined HAVE_GETPWUID
423 pw = getpwuid(getuid());
426 cx_string_delete(header);
433 user = getenv(
"USER");
434 user = user == NULL ? getenv(
"LOGNAME") : user;
437 cx_string_delete(header);
445 if (timestamp == NULL) {
446 cx_string_delete(header);
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);
459 if (self->id != NULL) {
460 _giraffe_paf_format_line(header, PAF_ID, self->id, NULL, TRUE);
463 _giraffe_paf_format_line(header, PAF_ID,
"", NULL, TRUE);
466 _giraffe_paf_format_line(header, PAF_NAME, self->name,
"Name of "
469 if (self->description != NULL) {
470 _giraffe_paf_format_line(header, PAF_DESC, self->description,
471 "Short description of PAF", TRUE);
474 _giraffe_paf_format_line(header, PAF_DESC,
"",
"Short "
475 "description of PAF", TRUE);
478 _giraffe_paf_format_line(header, PAF_CRTE_NAME, user,
"Name of "
480 _giraffe_paf_format_line(header, PAF_CRTE_TIME, timestamp,
481 "Civil time for creation", TRUE);
483 _giraffe_paf_format_line(header, PAF_LCHG_NAME,
"",
"Author of "
485 _giraffe_paf_format_line(header, PAF_LCHG_TIME,
"",
"Timestamp for "
486 "last change", TRUE);
488 _giraffe_paf_format_line(header, PAF_CHCK_NAME,
"",
"Name of appl. "
490 _giraffe_paf_format_line(header, PAF_CHCK_TIME,
"",
"Time for "
492 _giraffe_paf_format_line(header, PAF_CHCK_CHECKSUM,
"",
"Checksum "
493 "for the PAF", TRUE);
495 _giraffe_paf_format_line(header, PAF_HDR_END, NULL, NULL, TRUE);
502 fprintf(stream,
"%s", cx_string_get(header));
504 if (ferror(stream) != 0) {
506 cx_string_delete(header);
512 cx_string_delete(header);
521 giraffe_paf_new(
const cxchar *name,
const cxchar *type,
const cxchar *
id,
522 const cxchar *description)
528 if (name == NULL || type == NULL) {
532 self = cx_malloc(
sizeof *
self);
534 self->header = _giraffe_pafhdr_create(name, type,
id, description);
535 self->records = cpl_propertylist_new();
537 cx_assert(self->header != NULL);
538 cx_assert(self->records != NULL);
546 giraffe_paf_delete(GiPaf *
self)
550 if (self->records != NULL) {
551 cpl_propertylist_delete(self->records);
552 self->records = NULL;
555 if (self->header != NULL) {
556 _giraffe_pafhdr_destroy(self->header);
569 giraffe_paf_get_name(
const GiPaf *
self)
576 cx_assert(self->header != NULL);
577 cx_assert(self->header->name != NULL);
579 return self->header->name;
585 giraffe_paf_set_name(GiPaf *
self,
const cxchar *name)
588 cx_assert(
self != NULL);
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);
600 self->header->name = cx_strdup(name);
609 giraffe_paf_get_type(
const GiPaf *
self)
616 cx_assert(self->header != NULL);
617 cx_assert(self->header->type != NULL);
619 return self->header->type;
625 giraffe_paf_set_type(GiPaf *
self,
const cxchar *type)
628 cx_assert(
self != NULL);
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);
640 self->header->type = cx_strdup(type);
649 giraffe_paf_get_id(
const GiPaf *
self)
656 cx_assert(self->header != NULL);
658 return self->header->id;
664 giraffe_paf_set_id(GiPaf *
self,
const cxchar *
id)
667 cx_assert(
self != NULL);
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);
679 self->header->id = cx_strdup(
id);
688 giraffe_paf_get_description(
const GiPaf *
self)
695 cx_assert(self->header != NULL);
697 return self->header->description;
703 giraffe_paf_set_description(GiPaf *
self,
const cxchar *description)
706 cx_assert(
self != NULL);
708 if (description == NULL) {
712 if (self->header->description != NULL) {
713 self->header->description = cx_realloc(self->header->description,
714 (strlen(description) + 1) *
716 strcpy(self->header->description, description);
719 self->header->description = cx_strdup(description);
728 giraffe_paf_get_properties(
const GiPaf *
self)
735 cx_assert(self->records != NULL);
737 return self->records;
743 giraffe_paf_set_properties(GiPaf *
self,
const cpl_propertylist *properties)
746 cx_assert(
self != NULL);
748 if (properties == NULL) {
752 if (self->records != NULL) {
753 cpl_propertylist_delete(self->records);
756 self->records = cpl_propertylist_duplicate(properties);
764 giraffe_paf_write(
const GiPaf *
self)
776 cx_assert(self->header != NULL);
778 stream = fopen(giraffe_paf_get_name(
self),
"wb");
780 if (stream == NULL) {
789 status = _giraffe_pafhdr_write(self->header, stream);
803 if (self->records != NULL && !cpl_propertylist_is_empty(self->records)) {
805 cxchar buffer[PAF_RECORD_MAX];
809 cx_string *line = NULL;
813 memset(&buffer[1],
'-', 78);
815 fprintf(stream,
"%s\n", buffer);
817 if (ferror(stream) != 0) {
822 line = cx_string_new();
824 for (i = 0; i < cpl_propertylist_get_size(self->records); i++) {
826 cpl_property *p = cpl_propertylist_get(self->records, i);
829 status = _giraffe_paf_convert_property(line, p, FALSE);
832 cx_string_delete(line);
838 fprintf(stream,
"%s", cx_string_get(line));
840 if (ferror(stream) != 0) {
841 cx_string_delete(line);
848 cx_string_delete(line);