27#if defined HAVE_SYS_TYPES_H
28# include <sys/types.h>
32#include <cxmessages.h>
34#include <cxstrutils.h>
36#include <cpl_propertylist.h>
42#define PAF_HDR_START "PAF.HDR.START"
43#define PAF_TYPE "PAF.TYPE"
44#define PAF_ID "PAF.ID"
45#define PAF_NAME "PAF.NAME"
46#define PAF_DESC "PAF.DESC"
47#define PAF_CRTE_NAME "PAF.CRTE.NAME"
48#define PAF_CRTE_TIME "PAF.CRTE.DAYTIM"
49#define PAF_LCHG_NAME "PAF.LCHG.NAME"
50#define PAF_LCHG_TIME "PAF.LCHG.DAYTIM"
51#define PAF_CHCK_NAME "PAF.CHCK.NAME"
52#define PAF_CHCK_TIME "PAF.CHCK.DAYTIM"
53#define PAF_CHCK_CHECKSUM "PAF.CHCK.CHECKSUM"
54#define PAF_HDR_END "PAF.HDR.END"
61static const cxsize PAF_FIELD_OFFSET_VALUE = 20;
62static const cxsize PAF_FIELD_OFFSET_COMMENT = 45;
71static const cxsize PAF_RECORD_MAX = 256;
89typedef struct GiPafHdr GiPafHdr;
94 cpl_propertylist *records;
99_giraffe_paf_format_line(cx_string *line,
const cxchar *name,
100 const cxchar *value,
const cxchar *comment,
104 cxchar buffer[PAF_RECORD_MAX + 2];
110 cx_assert(line != NULL);
124 if (sz + 1 > PAF_RECORD_MAX) {
128 memset(buffer,
' ', PAF_RECORD_MAX + 1);
129 memcpy(buffer, name, sz);
135 if (cpos < PAF_FIELD_OFFSET_VALUE) {
136 cpos = PAF_FIELD_OFFSET_VALUE;
150 if (sz > PAF_RECORD_MAX - cpos + 1) {
154 memcpy(&buffer[cpos], value, sz);
159 buffer[cpos++] =
';';
169 if (comment != NULL && comment[0] !=
'\0' &&
170 (PAF_RECORD_MAX - cpos + 1) > 2) {
172 if (cpos < PAF_FIELD_OFFSET_COMMENT) {
173 cpos = PAF_FIELD_OFFSET_COMMENT;
179 memcpy(&buffer[cpos],
"# ", 2);
182 sz = strlen(comment);
183 sz = sz < PAF_RECORD_MAX - cpos + 1 ? sz : PAF_RECORD_MAX - cpos + 1;
185 memcpy(&buffer[cpos], comment, sz);
190 buffer[++cpos] =
'\0';
193 if (append == TRUE) {
194 cx_string_append(line, buffer);
197 cx_string_set(line, buffer);
206_giraffe_paf_convert_property(cx_string *line, cpl_property *property,
213 const cxchar *comment;
215 cx_string *value = NULL;
218 cx_assert(line != NULL);
220 if (property == NULL) {
224 value = cx_string_new();
226 switch (cpl_property_get_type(property)) {
229 cxchar c = cpl_property_get_char(property);
231 cx_string_sprintf(value,
"%c", c);
237 cxint b = cpl_property_get_bool(property);
240 cx_string_set(value,
"T");
243 cx_string_set(value,
"F");
250 cxint i = cpl_property_get_int(property);
252 cx_string_sprintf(value,
"%d", i);
258 cxlong l = cpl_property_get_long(property);
260 cx_string_sprintf(value,
"%ld", l);
266 cxfloat f = cpl_property_get_float(property);
268 cx_string_sprintf(value,
"%.15G", f);
270 if (!strchr(cx_string_get(value),
'.')) {
272 if (strchr(cx_string_get(value),
'E')) {
273 cx_string_sprintf(value,
"%.1E", f);
276 cx_string_append(value,
".");
282 case CPL_TYPE_DOUBLE:
284 cxdouble d = cpl_property_get_double(property);
286 cx_string_sprintf(value,
"%.15G", d);
288 if (!strchr(cx_string_get(value),
'.')) {
290 if (strchr(cx_string_get(value),
'E')) {
291 cx_string_sprintf(value,
"%.1E", d);
294 cx_string_append(value,
".");
300 case CPL_TYPE_STRING:
302 const cxchar *s = cpl_property_get_string(property);
304 cx_string_sprintf(value,
"\"%s\"", s);
315 cx_string_delete(value);
321 name = cpl_property_get_name(property);
322 comment = cpl_property_get_comment(property);
324 status = _giraffe_paf_format_line(line, name, cx_string_get(value),
328 cx_string_delete(value);
332 cx_string_delete(value);
339inline static GiPafHdr *
340_giraffe_pafhdr_create(
const cxchar *name,
const cxchar *type,
341 const cxchar *
id,
const cxchar *description)
344 GiPafHdr *self = cx_calloc(1,
sizeof *self);
347 self->name = cx_strdup(name);
348 self->type = cx_strdup(type);
351 self->id = cx_strdup(
id);
354 if (description != NULL) {
355 self->description = cx_strdup(description);
364_giraffe_pafhdr_destroy(GiPafHdr *self)
368 if (self->name != NULL) {
373 if (self->type != NULL) {
378 if (self->id != NULL) {
383 if (self->description != NULL) {
384 cx_free(self->description);
385 self->description = NULL;
397_giraffe_pafhdr_write(GiPafHdr *self, FILE *stream)
400 if (stream == NULL) {
409 cx_string *header = cx_string_new();
412#if defined HAVE_GETUID && defined HAVE_GETPWUID
416 pw = getpwuid(getuid());
419 cx_string_delete(header);
426 user = getenv(
"USER");
427 user = user == NULL ? getenv(
"LOGNAME") : user;
430 cx_string_delete(header);
438 if (timestamp == NULL) {
439 cx_string_delete(header);
448 _giraffe_paf_format_line(header, PAF_HDR_START, NULL, NULL, TRUE);
449 _giraffe_paf_format_line(header, PAF_TYPE, self->type,
"Type of "
450 "parameter file", TRUE);
452 if (self->id != NULL) {
453 _giraffe_paf_format_line(header, PAF_ID, self->id, NULL, TRUE);
456 _giraffe_paf_format_line(header, PAF_ID,
"", NULL, TRUE);
459 _giraffe_paf_format_line(header, PAF_NAME, self->name,
"Name of "
462 if (self->description != NULL) {
463 _giraffe_paf_format_line(header, PAF_DESC, self->description,
464 "Short description of PAF", TRUE);
467 _giraffe_paf_format_line(header, PAF_DESC,
"",
"Short "
468 "description of PAF", TRUE);
471 _giraffe_paf_format_line(header, PAF_CRTE_NAME, user,
"Name of "
473 _giraffe_paf_format_line(header, PAF_CRTE_TIME, timestamp,
474 "Civil time for creation", TRUE);
476 _giraffe_paf_format_line(header, PAF_LCHG_NAME,
"",
"Author of "
478 _giraffe_paf_format_line(header, PAF_LCHG_TIME,
"",
"Timestamp for "
479 "last change", TRUE);
481 _giraffe_paf_format_line(header, PAF_CHCK_NAME,
"",
"Name of appl. "
483 _giraffe_paf_format_line(header, PAF_CHCK_TIME,
"",
"Time for "
485 _giraffe_paf_format_line(header, PAF_CHCK_CHECKSUM,
"",
"Checksum "
486 "for the PAF", TRUE);
488 _giraffe_paf_format_line(header, PAF_HDR_END, NULL, NULL, TRUE);
495 fprintf(stream,
"%s", cx_string_get(header));
497 if (ferror(stream) != 0) {
499 cx_string_delete(header);
505 cx_string_delete(header);
514giraffe_paf_new(
const cxchar *name,
const cxchar *type,
const cxchar *
id,
515 const cxchar *description)
521 if (name == NULL || type == NULL) {
525 self = cx_malloc(
sizeof *self);
527 self->header = _giraffe_pafhdr_create(name, type,
id, description);
528 self->records = cpl_propertylist_new();
530 cx_assert(self->header != NULL);
531 cx_assert(self->records != NULL);
539giraffe_paf_delete(GiPaf *self)
543 if (self->records != NULL) {
544 cpl_propertylist_delete(self->records);
545 self->records = NULL;
548 if (self->header != NULL) {
549 _giraffe_pafhdr_destroy(self->header);
562giraffe_paf_get_name(
const GiPaf *self)
569 cx_assert(self->header != NULL);
570 cx_assert(self->header->name != NULL);
572 return self->header->name;
578giraffe_paf_set_name(GiPaf *self,
const cxchar *name)
581 cx_assert(self != NULL);
587 if (self->header->name != NULL) {
588 self->header->name = cx_realloc(self->header->name,
589 (strlen(name) + 1) *
sizeof(cxchar));
590 strcpy(self->header->name, name);
593 self->header->name = cx_strdup(name);
602giraffe_paf_get_type(
const GiPaf *self)
609 cx_assert(self->header != NULL);
610 cx_assert(self->header->type != NULL);
612 return self->header->type;
618giraffe_paf_set_type(GiPaf *self,
const cxchar *type)
621 cx_assert(self != NULL);
627 if (self->header->type != NULL) {
628 self->header->type = cx_realloc(self->header->type,
629 (strlen(type) + 1) *
sizeof(cxchar));
630 strcpy(self->header->type, type);
633 self->header->type = cx_strdup(type);
642giraffe_paf_get_id(
const GiPaf *self)
649 cx_assert(self->header != NULL);
651 return self->header->id;
657giraffe_paf_set_id(GiPaf *self,
const cxchar *
id)
660 cx_assert(self != NULL);
666 if (self->header->id != NULL) {
667 self->header->id = cx_realloc(self->header->id,
668 (strlen(
id) + 1) *
sizeof(cxchar));
669 strcpy(self->header->id,
id);
672 self->header->id = cx_strdup(
id);
681giraffe_paf_get_description(
const GiPaf *self)
688 cx_assert(self->header != NULL);
690 return self->header->description;
696giraffe_paf_set_description(GiPaf *self,
const cxchar *description)
699 cx_assert(self != NULL);
701 if (description == NULL) {
705 if (self->header->description != NULL) {
706 self->header->description = cx_realloc(self->header->description,
707 (strlen(description) + 1) *
709 strcpy(self->header->description, description);
712 self->header->description = cx_strdup(description);
721giraffe_paf_get_properties(
const GiPaf *self)
728 cx_assert(self->records != NULL);
730 return self->records;
736giraffe_paf_set_properties(GiPaf *self,
const cpl_propertylist *properties)
739 cx_assert(self != NULL);
741 if (properties == NULL) {
745 if (self->records != NULL) {
746 cpl_propertylist_delete(self->records);
749 self->records = cpl_propertylist_duplicate(properties);
757giraffe_paf_write(
const GiPaf *self)
769 cx_assert(self->header != NULL);
771 stream = fopen(giraffe_paf_get_name(self),
"wb");
773 if (stream == NULL) {
782 status = _giraffe_pafhdr_write(self->header, stream);
796 if (self->records != NULL && !cpl_propertylist_is_empty(self->records)) {
798 cxchar buffer[PAF_RECORD_MAX];
802 cx_string *line = NULL;
806 memset(&buffer[1],
'-', 78);
808 fprintf(stream,
"%s\n", buffer);
810 if (ferror(stream) != 0) {
815 line = cx_string_new();
817 for (i = 0; i < cpl_propertylist_get_size(self->records); i++) {
819 cpl_property *p = cpl_propertylist_get(self->records, i);
822 status = _giraffe_paf_convert_property(line, p, FALSE);
825 cx_string_delete(line);
831 fprintf(stream,
"%s", cx_string_get(line));
833 if (ferror(stream) != 0) {
834 cx_string_delete(line);
841 cx_string_delete(line);
cxchar * giraffe_localtime_iso8601(void)
Get the current date and time in ISO 8601 format.