GIRAFFE Pipeline Reference Manual

gipaf.c

00001 /* $Id: gipaf.c,v 1.7 2007/03/12 12:53:23 rpalsa Exp $
00002  *
00003  * This file is part of the GIRAFFE Pipeline
00004  * Copyright (C) 2002-2006 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author: rpalsa $
00023  * $Date: 2007/03/12 12:53:23 $
00024  * $Revision: 1.7 $
00025  * $Name: giraffe-2_9 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <pwd.h>
00035 #if defined HAVE_SYS_TYPES_H
00036 #  include <sys/types.h>
00037 #endif
00038 
00039 #include <cxmemory.h>
00040 #include <cxstring.h>
00041 #include <cxstrutils.h>
00042 
00043 #include <cpl_propertylist.h>
00044 
00045 #include "giutils.h"
00046 #include "gipaf.h"
00047 
00048 
00049 #define PAF_HDR_START      "PAF.HDR.START"
00050 #define PAF_TYPE           "PAF.TYPE"
00051 #define PAF_ID             "PAF.ID"
00052 #define PAF_NAME           "PAF.NAME"
00053 #define PAF_DESC           "PAF.DESC"
00054 #define PAF_CRTE_NAME      "PAF.CRTE.NAME"
00055 #define PAF_CRTE_TIME      "PAF.CRTE.DAYTIM"
00056 #define PAF_LCHG_NAME      "PAF.LCHG.NAME"
00057 #define PAF_LCHG_TIME      "PAF.LCHG.DAYTIM"
00058 #define PAF_CHCK_NAME      "PAF.CHCK.NAME"
00059 #define PAF_CHCK_TIME      "PAF.CHCK.DAYTIM"
00060 #define PAF_CHCK_CHECKSUM  "PAF.CHCK.CHECKSUM"
00061 #define PAF_HDR_END        "PAF.HDR.END"
00062 
00063 
00064 /*
00065  * Value and comment field start position
00066  */
00067 
00068 static const cxsize PAF_FIELD_OFFSET_VALUE = 20;
00069 static const cxsize PAF_FIELD_OFFSET_COMMENT = 45;
00070 
00071 
00072 /*
00073  * Maximum length of a parameter file record, i.e. maximum number of
00074  * characters per line of a parameter file on disk. This does not include
00075  * a trailing 0.
00076  */
00077 
00078 static const cxsize PAF_RECORD_MAX = 256;
00079 
00080 
00089 struct GiPafHdr {
00090     cxchar *name;
00091     cxchar *type;
00092     cxchar *id;
00093     cxchar *description;
00094 };
00095 
00096 typedef struct GiPafHdr GiPafHdr;
00097 
00098 
00099 struct GiPaf {
00100     GiPafHdr *header;
00101     cpl_propertylist *records;
00102 };
00103 
00104 
00105 inline static cxint
00106 _giraffe_paf_format_line(cx_string *line, const cxchar *name,
00107                            const cxchar *value, const cxchar *comment,
00108                            cxbool append)
00109 {
00110 
00111     cxchar buffer[PAF_RECORD_MAX + 2];
00112 
00113     cxsize sz = 0;
00114     cxsize cpos = 0;
00115 
00116 
00117     cx_assert(line != NULL);
00118 
00119     if (name == NULL) {
00120         return -1;
00121     }
00122 
00123 
00124     /*
00125      * Verify that the record name fits into the buffer. The extra
00126      * character is for the semicolon which has to be present.
00127      */
00128 
00129     sz = strlen(name);
00130 
00131     if (sz + 1 > PAF_RECORD_MAX) {
00132         return 1;
00133     }
00134 
00135     memset(buffer, ' ', PAF_RECORD_MAX + 1);
00136     memcpy(buffer, name, sz);
00137 
00138     cpos = sz;
00139 
00140     if (value != NULL) {
00141 
00142         if (cpos < PAF_FIELD_OFFSET_VALUE) {
00143             cpos = PAF_FIELD_OFFSET_VALUE;
00144         }
00145         else {
00146             ++cpos;
00147         }
00148 
00149         sz = strlen(value);
00150 
00151 
00152         /*
00153          * Verify that writing the value string does not overflow
00154          * the buffer.
00155          */
00156 
00157         if (sz > PAF_RECORD_MAX - cpos + 1) {
00158             return 2;
00159         }
00160 
00161         memcpy(&buffer[cpos], value, sz);
00162         cpos += sz;
00163 
00164     }
00165 
00166     buffer[cpos++] = ';';
00167 
00168 
00169     /*
00170      * Comments are only printed if there is room in the buffer for
00171      * at least 3 characters, so that not only the hash and the
00172      * following blank appear in the output because of the finite
00173      * record size.
00174      */
00175 
00176     if (comment != NULL && comment[0] != '\0' &&
00177         (PAF_RECORD_MAX - cpos + 1) > 2) {
00178 
00179         if (cpos < PAF_FIELD_OFFSET_COMMENT) {
00180             cpos = PAF_FIELD_OFFSET_COMMENT;
00181         }
00182         else {
00183             ++cpos;
00184         }
00185 
00186         memcpy(&buffer[cpos], "# ", 2);
00187         cpos += 2;
00188 
00189         sz = strlen(comment);
00190         sz = sz < PAF_RECORD_MAX - cpos + 1 ? sz : PAF_RECORD_MAX - cpos + 1;
00191 
00192         memcpy(&buffer[cpos], comment, sz);
00193         cpos += sz;
00194     }
00195 
00196     buffer[cpos] = '\n';
00197     buffer[++cpos] = '\0';
00198 
00199 
00200     if (append == TRUE) {
00201         cx_string_append(line, buffer);
00202     }
00203     else {
00204         cx_string_set(line, buffer);
00205     }
00206 
00207     return 0;
00208 
00209 }
00210 
00211 
00212 inline static cxint
00213 _giraffe_paf_convert_property(cx_string *line, cpl_property *property,
00214                               cxbool append)
00215 {
00216 
00217     cxint status = 0;
00218 
00219     const cxchar *name;
00220     const cxchar *comment;
00221 
00222     cx_string *value = NULL;
00223 
00224 
00225     cx_assert(line != NULL);
00226 
00227     if (property == NULL) {
00228         return -1;
00229     }
00230 
00231     value = cx_string_new();
00232 
00233     switch (cpl_property_get_type(property)) {
00234         case CPL_TYPE_CHAR:
00235         {
00236             cxchar c =  cpl_property_get_char(property);
00237 
00238             cx_string_sprintf(value, "%c", c);
00239         }
00240         break;
00241 
00242         case CPL_TYPE_BOOL:
00243         {
00244             cxint b = cpl_property_get_bool(property);
00245 
00246             if (b != 0) {
00247                 cx_string_set(value, "T");
00248             }
00249             else {
00250                 cx_string_set(value, "F");
00251             }
00252         }
00253         break;
00254 
00255         case CPL_TYPE_INT:
00256         {
00257             cxint i =  cpl_property_get_int(property);
00258 
00259             cx_string_sprintf(value, "%d", i);
00260         }
00261         break;
00262 
00263         case CPL_TYPE_LONG:
00264         {
00265             cxlong l =  cpl_property_get_long(property);
00266 
00267             cx_string_sprintf(value, "%ld", l);
00268         }
00269         break;
00270 
00271         case CPL_TYPE_FLOAT:
00272         {
00273             cxfloat f =  cpl_property_get_float(property);
00274 
00275             cx_string_sprintf(value, "%.15G", f);
00276 
00277             if (!strchr(cx_string_get(value), '.')) {
00278 
00279                 if (strchr(cx_string_get(value), 'E')) {
00280                     cx_string_sprintf(value, "%.1E", f);
00281                 }
00282                 else {
00283                     cx_string_append(value, ".");
00284                 }
00285             }
00286         }
00287         break;
00288 
00289         case CPL_TYPE_DOUBLE:
00290         {
00291             cxdouble d =  cpl_property_get_double(property);
00292 
00293             cx_string_sprintf(value, "%.15G", d);
00294 
00295             if (!strchr(cx_string_get(value), '.')) {
00296 
00297                 if (strchr(cx_string_get(value), 'E')) {
00298                     cx_string_sprintf(value, "%.1E", d);
00299                 }
00300                 else {
00301                     cx_string_append(value, ".");
00302                 }
00303             }
00304         }
00305         break;
00306 
00307         case CPL_TYPE_STRING:
00308         {
00309             const cxchar *s = cpl_property_get_string(property);
00310 
00311             cx_string_sprintf(value, "\"%s\"", s);
00312         }
00313         break;
00314 
00315         default:
00316 
00317             /*
00318              * Unsupported property type. This point should never be
00319              * reached!
00320              */
00321 
00322             cx_string_delete(value);
00323 
00324             return 1;
00325             break;
00326     }
00327 
00328     name = cpl_property_get_name(property);
00329     comment = cpl_property_get_comment(property);
00330 
00331     status = _giraffe_paf_format_line(line, name, cx_string_get(value),
00332                                       comment, append);
00333 
00334     if (status != 0) {
00335         cx_string_delete(value);
00336         return 2;
00337     }
00338 
00339     cx_string_delete(value);
00340 
00341     return 0;
00342 
00343 }
00344 
00345 
00346 inline static GiPafHdr *
00347 _giraffe_pafhdr_create(const cxchar *name, const cxchar *type,
00348                        const cxchar *id, const cxchar *description)
00349 {
00350 
00351     GiPafHdr *self = cx_calloc(1, sizeof *self);
00352 
00353 
00354     self->name = cx_strdup(name);
00355     self->type = cx_strdup(type);
00356 
00357     if (id != NULL) {
00358         self->id = cx_strdup(id);
00359     }
00360 
00361     if (description != NULL) {
00362         self->description = cx_strdup(description);
00363     }
00364 
00365     return self;
00366 
00367 }
00368 
00369 
00370 inline static void
00371 _giraffe_pafhdr_destroy(GiPafHdr *self)
00372 {
00373 
00374     if (self != NULL) {
00375         if (self->name != NULL) {
00376             cx_free(self->name);
00377             self->name = NULL;
00378         }
00379 
00380         if (self->type != NULL) {
00381             cx_free(self->type);
00382             self->type = NULL;
00383         }
00384 
00385         if (self->id != NULL) {
00386             cx_free(self->id);
00387             self->id = NULL;
00388         }
00389 
00390         if (self->description != NULL) {
00391             cx_free(self->description);
00392             self->description = NULL;
00393         }
00394 
00395         cx_free(self);
00396     }
00397 
00398     return;
00399 
00400 }
00401 
00402 
00403 inline static cxint
00404 _giraffe_pafhdr_write(GiPafHdr *self, FILE *stream)
00405 {
00406 
00407     if (stream == NULL) {
00408         return -1;
00409     }
00410 
00411     if (self != NULL) {
00412 
00413         cxchar *user;
00414         cxchar *timestamp;
00415 
00416         cx_string *header = cx_string_new();
00417 
00418 
00419 #if defined HAVE_GETUID && defined HAVE_GETPWUID
00420 
00421         struct passwd *pw;
00422 
00423         pw = getpwuid(getuid());
00424 
00425         if (pw == NULL) {
00426             cx_string_delete(header);
00427             return 1;
00428         }
00429 
00430         user = pw->pw_name;
00431 
00432 #else
00433         user = getenv("USER");
00434         user = user == NULL ? getenv("LOGNAME") : user;
00435 
00436         if (user == NULL) {
00437             cx_string_delete(header);
00438             return 1;
00439         }
00440 
00441 #endif
00442 
00443         timestamp = giraffe_localtime_iso8601();
00444 
00445         if (timestamp == NULL) {
00446             cx_string_delete(header);
00447             return 2;
00448         }
00449 
00450 
00451         /*
00452          * Write formatted header records to a string buffer
00453          */
00454 
00455         _giraffe_paf_format_line(header, PAF_HDR_START, NULL, NULL, TRUE);
00456         _giraffe_paf_format_line(header, PAF_TYPE, self->type, "Type of "
00457                                  "parameter file", TRUE);
00458 
00459         if (self->id != NULL) {
00460             _giraffe_paf_format_line(header, PAF_ID, self->id, NULL, TRUE);
00461         }
00462         else {
00463             _giraffe_paf_format_line(header, PAF_ID, "", NULL, TRUE);
00464         }
00465 
00466         _giraffe_paf_format_line(header, PAF_NAME, self->name, "Name of "
00467                                  "PAF", TRUE);
00468 
00469         if (self->description != NULL) {
00470             _giraffe_paf_format_line(header, PAF_DESC, self->description,
00471                                      "Short description of PAF", TRUE);
00472         }
00473         else {
00474             _giraffe_paf_format_line(header, PAF_DESC, "", "Short "
00475                                      "description of PAF", TRUE);
00476         }
00477 
00478         _giraffe_paf_format_line(header, PAF_CRTE_NAME, user, "Name of "
00479                                  "creator", TRUE);
00480         _giraffe_paf_format_line(header, PAF_CRTE_TIME, timestamp,
00481                                  "Civil time for creation", TRUE);
00482 
00483         _giraffe_paf_format_line(header, PAF_LCHG_NAME, "", "Author of "
00484                                  "par. file", TRUE);
00485         _giraffe_paf_format_line(header, PAF_LCHG_TIME, "", "Timestamp for "
00486                                  "last change", TRUE);
00487 
00488         _giraffe_paf_format_line(header, PAF_CHCK_NAME, "", "Name of appl. "
00489                                  "checking", TRUE);
00490         _giraffe_paf_format_line(header, PAF_CHCK_TIME, "", "Time for "
00491                                  "checking", TRUE);
00492         _giraffe_paf_format_line(header, PAF_CHCK_CHECKSUM, "", "Checksum "
00493                                  "for the PAF", TRUE);
00494 
00495         _giraffe_paf_format_line(header, PAF_HDR_END, NULL, NULL, TRUE);
00496 
00497 
00498         /*
00499          * Write string buffer contents to the output stream
00500          */
00501 
00502         fprintf(stream, "%s", cx_string_get(header));
00503 
00504         if (ferror(stream) != 0) {
00505             cx_free(timestamp);
00506             cx_string_delete(header);
00507 
00508             return 3;
00509         }
00510 
00511         cx_free(timestamp);
00512         cx_string_delete(header);
00513     }
00514 
00515     return 0;
00516 
00517 }
00518 
00519 
00520 GiPaf *
00521 giraffe_paf_new(const cxchar *name, const cxchar *type, const cxchar *id,
00522                 const cxchar *description)
00523 {
00524 
00525     GiPaf *self = NULL;
00526 
00527 
00528     if (name == NULL || type == NULL) {
00529         return NULL;
00530     }
00531 
00532     self = cx_malloc(sizeof *self);
00533 
00534     self->header = _giraffe_pafhdr_create(name, type, id, description);
00535     self->records = cpl_propertylist_new();
00536 
00537     cx_assert(self->header != NULL);
00538     cx_assert(self->records != NULL);
00539 
00540     return self;
00541 
00542 }
00543 
00544 
00545 void
00546 giraffe_paf_delete(GiPaf *self)
00547 {
00548 
00549     if (self != NULL) {
00550         if (self->records != NULL) {
00551             cpl_propertylist_delete(self->records);
00552             self->records = NULL;
00553         }
00554 
00555         if (self->header != NULL) {
00556             _giraffe_pafhdr_destroy(self->header);
00557             self->header = NULL;
00558         }
00559 
00560         cx_free(self);
00561     }
00562 
00563     return;
00564 
00565 }
00566 
00567 
00568 cxchar *
00569 giraffe_paf_get_name(const GiPaf *self)
00570 {
00571 
00572     if (self == NULL) {
00573         return NULL;
00574     }
00575 
00576     cx_assert(self->header != NULL);
00577     cx_assert(self->header->name != NULL);
00578 
00579     return self->header->name;
00580 
00581 }
00582 
00583 
00584 cxint
00585 giraffe_paf_set_name(GiPaf *self, const cxchar *name)
00586 {
00587 
00588     cx_assert(self != NULL);
00589 
00590     if (name == NULL) {
00591         return -1;
00592     }
00593 
00594     if (self->header->name != NULL) {
00595         self->header->name = cx_realloc(self->header->name,
00596                                         (strlen(name) + 1) * sizeof(cxchar));
00597         strcpy(self->header->name, name);
00598     }
00599     else {
00600         self->header->name = cx_strdup(name);
00601     }
00602 
00603     return 0;
00604 
00605 }
00606 
00607 
00608 cxchar *
00609 giraffe_paf_get_type(const GiPaf *self)
00610 {
00611 
00612     if (self == NULL) {
00613         return NULL;
00614     }
00615 
00616     cx_assert(self->header != NULL);
00617     cx_assert(self->header->type != NULL);
00618 
00619     return self->header->type;
00620 
00621 }
00622 
00623 
00624 cxint
00625 giraffe_paf_set_type(GiPaf *self, const cxchar *type)
00626 {
00627 
00628     cx_assert(self != NULL);
00629 
00630     if (type == NULL) {
00631         return -1;
00632     }
00633 
00634     if (self->header->type != NULL) {
00635         self->header->type = cx_realloc(self->header->type,
00636                                         (strlen(type) + 1) * sizeof(cxchar));
00637         strcpy(self->header->type, type);
00638     }
00639     else {
00640         self->header->type = cx_strdup(type);
00641     }
00642 
00643     return 0;
00644 
00645 }
00646 
00647 
00648 cxchar *
00649 giraffe_paf_get_id(const GiPaf *self)
00650 {
00651 
00652     if (self == NULL) {
00653         return NULL;
00654     }
00655 
00656     cx_assert(self->header != NULL);
00657 
00658     return self->header->id;
00659 
00660 }
00661 
00662 
00663 cxint
00664 giraffe_paf_set_id(GiPaf *self, const cxchar *id)
00665 {
00666 
00667     cx_assert(self != NULL);
00668 
00669     if (id == NULL) {
00670         return -1;
00671     }
00672 
00673     if (self->header->id != NULL) {
00674         self->header->id = cx_realloc(self->header->id,
00675                                       (strlen(id) + 1) * sizeof(cxchar));
00676         strcpy(self->header->id, id);
00677     }
00678     else {
00679         self->header->id = cx_strdup(id);
00680     }
00681 
00682     return 0;
00683 
00684 }
00685 
00686 
00687 cxchar *
00688 giraffe_paf_get_description(const GiPaf *self)
00689 {
00690 
00691     if (self == NULL) {
00692         return NULL;
00693     }
00694 
00695     cx_assert(self->header != NULL);
00696 
00697     return self->header->description;
00698 
00699 }
00700 
00701 
00702 cxint
00703 giraffe_paf_set_description(GiPaf *self, const cxchar *description)
00704 {
00705 
00706     cx_assert(self != NULL);
00707 
00708     if (description == NULL) {
00709         return -1;
00710     }
00711 
00712     if (self->header->description != NULL) {
00713         self->header->description = cx_realloc(self->header->description,
00714                                                (strlen(description) + 1) *
00715                                                sizeof(cxchar));
00716         strcpy(self->header->description, description);
00717     }
00718     else {
00719         self->header->description = cx_strdup(description);
00720     }
00721 
00722     return 0;
00723 
00724 }
00725 
00726 
00727 cpl_propertylist *
00728 giraffe_paf_get_properties(const GiPaf *self)
00729 {
00730 
00731     if (self == NULL) {
00732         return NULL;
00733     }
00734 
00735     cx_assert(self->records != NULL);
00736 
00737     return self->records;
00738 
00739 }
00740 
00741 
00742 cxint
00743 giraffe_paf_set_properties(GiPaf *self, const cpl_propertylist *properties)
00744 {
00745 
00746     cx_assert(self != NULL);
00747 
00748     if (properties == NULL) {
00749         return -1;
00750     }
00751 
00752     if (self->records != NULL) {
00753         cpl_propertylist_delete(self->records);
00754     }
00755 
00756     self->records = cpl_propertylist_duplicate(properties);
00757 
00758     return 0;
00759 
00760 }
00761 
00762 
00763 cxint
00764 giraffe_paf_write(const GiPaf *self)
00765 {
00766 
00767     cxint status = 0;
00768 
00769     FILE *stream = NULL;
00770 
00771 
00772     if (self == NULL) {
00773         return -1;
00774     }
00775 
00776     cx_assert(self->header != NULL);
00777 
00778     stream = fopen(giraffe_paf_get_name(self), "wb");
00779 
00780     if (stream == NULL) {
00781         return 1;
00782     }
00783 
00784 
00785     /*
00786      * Write PAF header
00787      */
00788 
00789     status = _giraffe_pafhdr_write(self->header, stream);
00790 
00791     if (status != 0) {
00792         fclose(stream);
00793         return 2;
00794     }
00795 
00796     fflush(stream);
00797 
00798 
00799     /*
00800      * Write PAF records
00801      */
00802 
00803     if (self->records != NULL && !cpl_propertylist_is_empty(self->records)) {
00804 
00805         cxchar buffer[PAF_RECORD_MAX];
00806 
00807         register cxlong i;
00808 
00809         cx_string *line = NULL;
00810 
00811 
00812         buffer[0] = '#';
00813         memset(&buffer[1], '-', 78);
00814         buffer[79] = '\0';
00815         fprintf(stream, "%s\n", buffer);
00816 
00817         if (ferror(stream) != 0) {
00818             fclose(stream);
00819             return 3;
00820         }
00821 
00822         line = cx_string_new();
00823 
00824         for (i = 0; i < cpl_propertylist_get_size(self->records); i++) {
00825 
00826             cpl_property *p = cpl_propertylist_get(self->records, i);
00827 
00828 
00829             status = _giraffe_paf_convert_property(line, p, FALSE);
00830 
00831             if (status != 0) {
00832                 cx_string_delete(line);
00833                 fclose(stream);
00834 
00835                 return 4;
00836             }
00837 
00838             fprintf(stream, "%s", cx_string_get(line));
00839 
00840             if (ferror(stream) != 0) {
00841                 cx_string_delete(line);
00842                 fclose(stream);
00843 
00844                 return 5;
00845             }
00846         }
00847 
00848         cx_string_delete(line);
00849         fflush(stream);
00850 
00851     }
00852 
00853     fclose(stream);
00854 
00855     return 0;
00856 
00857 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:28 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004