IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 1, 2006, 2:55:23 PM (20 years ago)
Author:
Paul Price
Message:

Addition of a vast quantity of assertions in public functions. Adopted a policy of using assert() within file-static functions (since they are only called internally, any errors there are problems with the program) and using the PS_ASSERT_WHATEVER() macros within public functions. Cleaned a few things up in the process.

Location:
trunk/psModules/src/concepts
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/concepts/pmConcepts.c

    r7017 r7278  
    4444                      )
    4545{
    46     assert(blank);
     46    PS_ASSERT_PTR_NON_NULL(blank, false);
     47
    4748    if (!conceptsInitialised) {
    4849        pmConceptsInit();
     
    8081                         )
    8182{
     83    assert(specs);
     84    assert(target);
     85
    8286    if (!conceptsInitialised) {
    8387        pmConceptsInit();
     
    119123                        )
    120124{
     125    assert(specs);
     126    assert(read);
     127    assert(target);
     128
    121129    if (!conceptsInitialised) {
    122130        pmConceptsInit();
     
    156164                         )
    157165{
     166    assert(specs);
     167    assert(concepts);
     168
    158169    if (!conceptsInitialised) {
    159170        pmConceptsInit();
     
    180191                       )
    181192{
     193    PS_ASSERT_PTR_NON_NULL(fpa, false);
    182194    psTrace("psModule.concepts", 5, "Blanking FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    183195    return conceptsBlank(&conceptsFPA, fpa->concepts);
     
    191203                      )
    192204{
     205    PS_ASSERT_PTR_NON_NULL(fpa, false);
    193206    psTrace("psModule.concepts", 5, "Reading FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    194207    return conceptsRead(&conceptsFPA, fpa, NULL, NULL, &fpa->conceptsRead, source, db, fpa->concepts);
     
    201214                       )
    202215{
     216    PS_ASSERT_PTR_NON_NULL(fpa, false);
    203217    psTrace("psModule.concepts", 5, "Writing FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    204218    return conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, db, fpa->concepts);
     
    209223                        )
    210224{
     225    PS_ASSERT_PTR_NON_NULL(chip, false);
    211226    psTrace("psModule.concepts", 5, "Blanking chip concepts: %x %x\n", conceptsChip, chip->concepts);
    212227    return conceptsBlank(&conceptsChip, chip->concepts);
     
    220235                       )
    221236{
     237    PS_ASSERT_PTR_NON_NULL(chip, false);
    222238    psTrace("psModule.concepts", 5, "Reading chip concepts: %x %x\n", conceptsChip, chip->concepts);
    223239    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     
    235251                        )
    236252{
     253    PS_ASSERT_PTR_NON_NULL(chip, false);
    237254    psTrace("psModule.concepts", 5, "Writing chip concepts: %x %x\n", conceptsChip, chip->concepts);
    238255    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     
    246263                        )
    247264{
     265    PS_ASSERT_PTR_NON_NULL(cell, false);
    248266    psTrace("psModule.concepts", 5, "Blanking cell concepts: %x %x\n", conceptsCell, cell->concepts);
    249267    return conceptsBlank(&conceptsCell, cell->concepts);
     
    257275                       )
    258276{
     277    PS_ASSERT_PTR_NON_NULL(cell, false);
    259278    psTrace("psModule.concepts", 5, "Reading cell concepts: %x %x\n", conceptsCell, cell->concepts);
    260279    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     
    274293                        )
    275294{
     295    PS_ASSERT_PTR_NON_NULL(cell, false);
    276296    psTrace("psModule.concepts", 5, "Writing cell concepts: %x %x\n", conceptsCell, cell->concepts);
    277297    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     
    336356        {
    337357            psMetadataItem *fpaRa = psMetadataItemAllocF64("FPA.RA", "Right Ascension of boresight", NAN);
    338             pmConceptRegister(fpaRa, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
    339                               (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_FPA_LEVEL_FPA);
     358            pmConceptRegister(fpaRa, (pmConceptParseFunc)p_pmConceptParse_FPA_Coords,
     359                              (pmConceptFormatFunc)p_pmConceptFormat_FPA_Coords, PM_FPA_LEVEL_FPA);
    340360            psFree(fpaRa);
    341361        }
     
    344364        {
    345365            psMetadataItem *fpaDec = psMetadataItemAllocF64("FPA.DEC", "Declination of boresight", NAN);
    346             pmConceptRegister(fpaDec, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
    347                               (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_FPA_LEVEL_FPA);
     366            pmConceptRegister(fpaDec, (pmConceptParseFunc)p_pmConceptParse_FPA_Coords,
     367                              (pmConceptFormatFunc)p_pmConceptFormat_FPA_Coords, PM_FPA_LEVEL_FPA);
    348368            psFree(fpaDec);
    349369        }
     
    446466                                          "Trim section", trimsec);
    447467            psFree(trimsec);
    448             pmConceptRegister(cellTrimsec, (pmConceptParseFunc)pmConceptParse_CELL_TRIMSEC,
    449                               (pmConceptFormatFunc)pmConceptFormat_CELL_TRIMSEC, PM_FPA_LEVEL_CELL);
     468            pmConceptRegister(cellTrimsec, (pmConceptParseFunc)p_pmConceptParse_CELL_TRIMSEC,
     469                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_TRIMSEC, PM_FPA_LEVEL_CELL);
    450470            psFree(cellTrimsec);
    451471        }
     
    457477                                          "Bias sections", biassecs);
    458478            psFree(biassecs);
    459             pmConceptRegister(cellBiassec, (pmConceptParseFunc)pmConceptParse_CELL_BIASSEC,
    460                               (pmConceptFormatFunc)pmConceptFormat_CELL_BIASSEC, PM_FPA_LEVEL_CELL);
     479            pmConceptRegister(cellBiassec, (pmConceptParseFunc)p_pmConceptParse_CELL_BIASSEC,
     480                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_BIASSEC, PM_FPA_LEVEL_CELL);
    461481            psFree(cellBiassec);
    462482        }
     
    465485        {
    466486            psMetadataItem *cellXbin = psMetadataItemAllocS32("CELL.XBIN", "Binning in x", 0);
    467             pmConceptRegister(cellXbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
    468                               (pmConceptFormatFunc)pmConceptFormat_CELL_XBIN, PM_FPA_LEVEL_CELL);
     487            pmConceptRegister(cellXbin, (pmConceptParseFunc)p_pmConceptParse_CELL_Binning,
     488                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_XBIN, PM_FPA_LEVEL_CELL);
    469489            psFree(cellXbin);
    470490        }
     
    473493        {
    474494            psMetadataItem *cellYbin = psMetadataItemAllocS32("CELL.YBIN", "Binning in y", 0);
    475             pmConceptRegister(cellYbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
    476                               (pmConceptFormatFunc)pmConceptFormat_CELL_YBIN, PM_FPA_LEVEL_CELL);
     495            pmConceptRegister(cellYbin, (pmConceptParseFunc)p_pmConceptParse_CELL_Binning,
     496                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_YBIN, PM_FPA_LEVEL_CELL);
    477497            psFree(cellYbin);
    478498        }
     
    481501        {
    482502            psMetadataItem *cellTimesys = psMetadataItemAllocS32("CELL.TIMESYS", "Time system", -1);
    483             pmConceptRegister(cellTimesys, (pmConceptParseFunc)pmConceptParse_CELL_TIMESYS,
    484                               (pmConceptFormatFunc)pmConceptFormat_CELL_TIMESYS, PM_FPA_LEVEL_CELL);
     503            pmConceptRegister(cellTimesys, (pmConceptParseFunc)p_pmConceptParse_CELL_TIMESYS,
     504                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_TIMESYS, PM_FPA_LEVEL_CELL);
    485505            psFree(cellTimesys);
    486506        }
     
    495515                                       "Time of exposure", time);
    496516            psFree(time);
    497             pmConceptRegister(cellTime, (pmConceptParseFunc)pmConceptParse_CELL_TIME,
    498                               (pmConceptFormatFunc)pmConceptFormat_CELL_TIME, PM_FPA_LEVEL_CELL);
     517            pmConceptRegister(cellTime, (pmConceptParseFunc)p_pmConceptParse_CELL_TIME,
     518                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_TIME, PM_FPA_LEVEL_CELL);
    499519            psFree(cellTime);
    500520        }
     
    503523        {
    504524            psMetadataItem *cellX0 = psMetadataItemAllocS32("CELL.X0", "Position of (0,0) on the chip", 0);
    505             pmConceptRegister(cellX0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
    506                               (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_FPA_LEVEL_CELL);
     525            pmConceptRegister(cellX0, (pmConceptParseFunc)p_pmConceptParse_CELL_Positions,
     526                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_Positions, PM_FPA_LEVEL_CELL);
    507527            psFree(cellX0);
    508528        }
     
    511531        {
    512532            psMetadataItem *cellY0 = psMetadataItemAllocS32("CELL.Y0", "Position of (0,0) on the chip", 0);
    513             pmConceptRegister(cellY0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
    514                               (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_FPA_LEVEL_CELL);
     533            pmConceptRegister(cellY0, (pmConceptParseFunc)p_pmConceptParse_CELL_Positions,
     534                              (pmConceptFormatFunc)p_pmConceptFormat_CELL_Positions, PM_FPA_LEVEL_CELL);
    515535            psFree(cellY0);
    516536        }
     
    534554                      )
    535555{
     556    PS_ASSERT_PTR_NON_NULL(target, false);
     557    PS_ASSERT_PTR_NON_NULL(source, false);
     558
    536559    // Copy FPA concepts
    537560    target->concepts = psMetadataCopy(target->concepts, source->concepts);
  • trunk/psModules/src/concepts/pmConceptsRead.c

    r7017 r7278  
    11#include <stdio.h>
     2#include <assert.h>
    23
    34#include "pslib.h"
     
    2122                                 )
    2223{
     24    assert(concept);
     25    assert(pattern);
     26
    2327    switch (pattern->type) {
    2428    case PS_DATA_STRING: {
     
    5357                        )
    5458{
    55     if (concept) {
    56         psMetadataItem *parsed = NULL;  // The parsed concept
    57         if (spec->parse) {
    58             parsed = spec->parse(concept, spec->blank, cameraFormat, fpa, chip, cell);
    59         } else {
    60             parsed = parsePlain(concept, spec->blank);
    61         }
    62 
    63         // Plug the parsed concept into a new psMetadataItem, so each "concept" has its own version that can
    64         // be altered without affecting the others.  Also, so that we maintain the template name and comment.
    65         psMetadataItem *cleaned = NULL;     // Item that's been cleaned up --- correct name and comment
    66         switch (spec->blank->type) {
    67         case PS_DATA_STRING:
    68             cleaned = psMetadataItemAllocStr(spec->blank->name, spec->blank->comment, parsed->data.V);
    69             break;
    70         case PS_DATA_S32:
    71             cleaned = psMetadataItemAllocS32(spec->blank->name, spec->blank->comment, parsed->data.S32);
    72             break;
    73         case PS_DATA_F32:
    74             cleaned = psMetadataItemAllocF32(spec->blank->name, spec->blank->comment, parsed->data.F32);
    75             break;
    76         case PS_DATA_F64:
    77             cleaned = psMetadataItemAllocF64(spec->blank->name, spec->blank->comment, parsed->data.F64);
    78             break;
    79         default:
    80             cleaned = psMetadataItemAlloc(spec->blank->name, parsed->type, spec->blank->comment,
    81                                           parsed->data.V);
    82         }
    83         psFree(parsed);
    84         psMetadataAddItem(target, cleaned, PS_LIST_TAIL, PS_META_REPLACE);
    85         psFree(cleaned);                 // Drop reference
    86         return true;
    87     }
    88 
    89     return false;
     59    assert(spec);
     60    assert(cameraFormat);
     61    assert(target);
     62
     63    if (!concept) {
     64        return false;
     65    }
     66
     67    psMetadataItem *parsed = NULL;  // The parsed concept
     68    if (spec->parse) {
     69        parsed = spec->parse(concept, spec->blank, cameraFormat, fpa, chip, cell);
     70    } else {
     71        parsed = parsePlain(concept, spec->blank);
     72    }
     73
     74    // Plug the parsed concept into a new psMetadataItem, so each "concept" has its own version that can
     75    // be altered without affecting the others.  Also, so that we maintain the template name and comment.
     76    psMetadataItem *cleaned = NULL;     // Item that's been cleaned up --- correct name and comment
     77    switch (spec->blank->type) {
     78    case PS_DATA_STRING:
     79        cleaned = psMetadataItemAllocStr(spec->blank->name, spec->blank->comment, parsed->data.V);
     80        break;
     81    case PS_DATA_S32:
     82        cleaned = psMetadataItemAllocS32(spec->blank->name, spec->blank->comment, parsed->data.S32);
     83        break;
     84    case PS_DATA_F32:
     85        cleaned = psMetadataItemAllocF32(spec->blank->name, spec->blank->comment, parsed->data.F32);
     86        break;
     87    case PS_DATA_F64:
     88        cleaned = psMetadataItemAllocF64(spec->blank->name, spec->blank->comment, parsed->data.F64);
     89        break;
     90    default:
     91        cleaned = psMetadataItemAlloc(spec->blank->name, parsed->type, spec->blank->comment,
     92                                      parsed->data.V);
     93    }
     94    psFree(parsed);
     95    psMetadataAddItem(target, cleaned, PS_LIST_TAIL, PS_META_REPLACE);
     96    psFree(cleaned);                 // Drop reference
     97    return true;
    9098}
    9199
     
    100108                             )
    101109{
    102     if (cell) {
    103         pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
    104         if (! hdu) {
    105             return false;
    106         }
    107         psMetadata *cameraFormat = hdu->format; // The camera format
    108         psMetadata *cellConfig = cell->config; // The camera configuration for this cell
    109         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    110         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    111         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    112             pmConceptSpec *spec = specItem->data.V; // The specification
    113             psString name = specItem->name; // The concept name
    114             psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL
    115             psMetadataItem *value = NULL; // The value of the concept
    116             if (conceptItem) {
    117                 if (conceptItem->type == PS_DATA_STRING) {
    118                     // Check the SOURCE
    119                     psString nameSource = NULL; // String with the concept name and ".SOURCE" added
    120                     psStringAppend(&nameSource, "%s.SOURCE", name);
    121                     bool mdok = true;       // Status of MD lookup
    122                     psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
    123                     psFree(nameSource);
    124                     if (mdok && strlen(source) > 0 && strcasecmp(source, "VALUE") == 0) {
    125                         value = conceptItem;
    126                         conceptParse(spec, value, cameraFormat, target, NULL, NULL, cell);
    127                     } else if (source && (strlen(source) == 0 || strcasecmp(source, "HEADER") != 0)) {
    128                         // We leave "HEADER" to pmConceptsReadFromHeader
    129                         psError(PS_ERR_IO, true, "%s isn't HEADER or VALUE --- can't read %s\n", source,
    130                                 name);
    131                         continue;
    132                     }
    133                 } else {
    134                     // Another type --- should be OK
    135                     conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell);
     110    PS_ASSERT_PTR_NON_NULL(specs, false);
     111    PS_ASSERT_PTR_NON_NULL(target, false);
     112    if (!cell) {
     113        return false;
     114    }
     115
     116    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
     117    if (! hdu) {
     118        return false;
     119    }
     120    psMetadata *cameraFormat = hdu->format; // The camera format
     121    psMetadata *cellConfig = cell->config; // The camera configuration for this cell
     122    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     123    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     124    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     125        pmConceptSpec *spec = specItem->data.V; // The specification
     126        psString name = specItem->name; // The concept name
     127        psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL
     128        psMetadataItem *value = NULL; // The value of the concept
     129        if (conceptItem) {
     130            if (conceptItem->type == PS_DATA_STRING) {
     131                // Check the SOURCE
     132                psString nameSource = NULL; // String with the concept name and ".SOURCE" added
     133                psStringAppend(&nameSource, "%s.SOURCE", name);
     134                bool mdok = true;       // Status of MD lookup
     135                psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
     136                psFree(nameSource);
     137                if (mdok && strlen(source) > 0 && strcasecmp(source, "VALUE") == 0) {
     138                    value = conceptItem;
     139                    conceptParse(spec, value, cameraFormat, target, NULL, NULL, cell);
     140                } else if (source && (strlen(source) == 0 || strcasecmp(source, "HEADER") != 0)) {
     141                    // We leave "HEADER" to pmConceptsReadFromHeader
     142                    psError(PS_ERR_IO, true, "%s isn't HEADER or VALUE --- can't read %s\n", source,
     143                            name);
     144                    continue;
    136145                }
     146            } else {
     147                // Another type --- should be OK
     148                conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell);
    137149            }
    138150        }
    139         psFree(specsIter);
    140         return true;
    141     }
    142     return false;
     151    }
     152    psFree(specsIter);
     153    return true;
    143154}
    144155
     
    151162                               )
    152163{
     164    PS_ASSERT_PTR_NON_NULL(specs, false);
     165    PS_ASSERT_PTR_NON_NULL(target, false);
     166
    153167    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    154168    if (!hdu) {
     
    158172    bool mdok = true;                   // Status of MD lookup
    159173    psMetadata *defaults = psMetadataLookupMD(&mdok, cameraFormat, "DEFAULTS"); // The DEFAULTS spec
    160     if (mdok && defaults) {
    161         pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    162         psMetadata *cameraFormat = hdu->format; // The camera format
    163         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    164         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    165         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    166             pmConceptSpec *spec = specItem->data.V; // The specification
    167             psString name = specItem->name; // The concept name
    168             psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL
    169             conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
    170         }
    171         psFree(specsIter);
    172         return true;
    173     }
    174     return false;
     174    if (!mdok || !defaults) {
     175        return false;
     176    }
     177    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     178    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     179    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     180        pmConceptSpec *spec = specItem->data.V; // The specification
     181        psString name = specItem->name; // The concept name
     182        psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL
     183        conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
     184    }
     185    psFree(specsIter);
     186    return true;
    175187}
    176188
     
    183195                             )
    184196{
     197    PS_ASSERT_PTR_NON_NULL(specs, false);
     198    PS_ASSERT_PTR_NON_NULL(target, false);
     199
    185200    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    186201    if (!hdu) {
     
    190205    bool mdok = true;                   // Status of MD lookup
    191206    psMetadata *transSpec = psMetadataLookupMD(&mdok, cameraFormat, "TRANSLATION"); // The TRANSLATION spec
    192     if (mdok && transSpec) {
    193         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    194         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    195         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    196             pmConceptSpec *spec = specItem->data.V; // The specification
    197             psString name = specItem->name; // The concept name
    198             psMetadataItem *headerItem = NULL; // The value of the concept from the header
    199             // First check the cell configuration
    200             if (cell && cell->config) {
    201                 psMetadataItem *conceptItem = psMetadataLookup(cell->config, name); // The concept, or NULL
    202                 if (conceptItem) {
    203                     // Check the SOURCE
    204                     psString nameSource = NULL; // String with the concept name and ".SOURCE" added
    205                     psStringAppend(&nameSource, "%s.SOURCE", name);
    206                     psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
    207                     psFree(nameSource);
    208                     if (mdok && strlen(source) && strcasecmp(source, "HEADER") == 0) {
    209                         headerItem = psMetadataLookup(hdu->header, conceptItem->data.V);
     207    if (!mdok || !transSpec) {
     208        return false;
     209    }
     210
     211    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     212    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     213    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     214        pmConceptSpec *spec = specItem->data.V; // The specification
     215        psString name = specItem->name; // The concept name
     216        psMetadataItem *headerItem = NULL; // The value of the concept from the header
     217        // First check the cell configuration
     218        if (cell && cell->config) {
     219            psMetadataItem *conceptItem = psMetadataLookup(cell->config, name); // The concept, or NULL
     220            if (conceptItem) {
     221                // Check the SOURCE
     222                psString nameSource = NULL; // String with the concept name and ".SOURCE" added
     223                psStringAppend(&nameSource, "%s.SOURCE", name);
     224                psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
     225                psFree(nameSource);
     226                if (mdok && strlen(source) && strcasecmp(source, "HEADER") == 0) {
     227                    headerItem = psMetadataLookup(hdu->header, conceptItem->data.V);
     228                }
     229                // Leave the error handling to pmConceptsFromCamera, which should already have been called
     230            }
     231        }
     232        if (! headerItem) {
     233            psString keywords = psMetadataLookupStr(&mdok, transSpec, name); // The FITS keywords
     234            if (mdok && strlen(keywords) > 0) {
     235                // In case there are multiple headers
     236                psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
     237                if (keys->n == 1) {
     238                    // Only one key --- proceed as usual
     239                    headerItem = psMetadataLookup(hdu->header, keywords);
     240                } else {
     241                    psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator
     242                    psString key = NULL; // Item from iteration
     243                    psList *values = psListAlloc(NULL); // List containing the values
     244                    while ((key = psListGetAndIncrement(keysIter))) {
     245                        psMetadataItem *value = psMetadataLookup(hdu->header, key);
     246                        psListAdd(values, PS_LIST_TAIL, value);
    210247                    }
    211                     // Leave the error handling to pmConceptsFromCamera, which should already have been called
     248                    psFree(keysIter);
     249                    headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values);
     250                    psFree(values);
    212251                }
     252                psFree(keys);
    213253            }
    214             if (! headerItem) {
    215                 psString keywords = psMetadataLookupStr(&mdok, transSpec, name); // The FITS keywords
    216                 if (mdok && strlen(keywords) > 0) {
    217                     // In case there are multiple headers
    218                     psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
    219                     if (keys->n == 1) {
    220                         // Only one key --- proceed as usual
    221                         headerItem = psMetadataLookup(hdu->header, keywords);
    222                     } else {
    223                         psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator
    224                         psString key = NULL; // Item from iteration
    225                         psList *values = psListAlloc(NULL); // List containing the values
    226                         while ((key = psListGetAndIncrement(keysIter))) {
    227                             psMetadataItem *value = psMetadataLookup(hdu->header, key);
    228                             psListAdd(values, PS_LIST_TAIL, value);
    229                         }
    230                         psFree(keysIter);
    231                         headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values);
    232                         psFree(values);
    233                     }
    234                     psFree(keys);
    235                 }
    236             }
    237 
    238             // This will also clean up the name
    239             conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell);
    240254        }
    241         psFree(specsIter);
    242         return true;
    243     }
    244     return false;
     255
     256        // This will also clean up the name
     257        conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell);
     258    }
     259    psFree(specsIter);
     260    return true;
    245261}
    246262
     
    255271                               )
    256272{
     273    PS_ASSERT_PTR_NON_NULL(specs, false);
     274    PS_ASSERT_PTR_NON_NULL(target, false);
     275
    257276    #ifdef OMIT_PSDB
     277
    258278    return false;
    259279    #else
     
    266286    bool mdok = true;                   // Status of MD lookup
    267287    psMetadata *dbSpec = psMetadataLookupMD(&mdok, cameraFormat, "DATABSE"); // The DATABASE spec
    268     if (mdok && dbSpec) {
    269         pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    270         psMetadata *cameraFormat = hdu->format; // The camera format
    271         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    272         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    273         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    274             pmConceptSpec *spec = specItem->data.V; // The specification
    275             psString name = specItem->name; // The concept name
    276 
    277             psMetadata *dbLookup = psMetadataLookupMD(&mdok, dbSpec, name);
    278             if (mdok && dbLookup) {
    279                 const char *tableName = psMetadataLookupStr(&mdok, dbLookup, "TABLE"); // Table name
    280                 // Names of the "where" columns
    281                 const char *givenCols = psMetadataLookupStr(&mdok, dbLookup, "GIVENDBCOL");
    282                 // Values of the "where" columns
    283                 const char *givenPS = psMetadataLookupStr(&mdok, dbLookup, "GIVENPS");
    284 
    285                 // Now, need to get the "given"s
    286                 if (strlen(givenCols) > 0 || strlen(givenPS) > 0) {
    287                     psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
    288                     psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
    289                     psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
    290                     if (cols->n != values->n) {
     288    if (!mdok || !dbSpec) {
     289        return false;
     290    }
     291
     292    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     293    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     294    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     295        pmConceptSpec *spec = specItem->data.V; // The specification
     296        psString name = specItem->name; // The concept name
     297
     298        psMetadata *dbLookup = psMetadataLookupMD(&mdok, dbSpec, name);
     299        if (mdok && dbLookup) {
     300            const char *tableName = psMetadataLookupStr(&mdok, dbLookup, "TABLE"); // Table name
     301            // Names of the "where" columns
     302            const char *givenCols = psMetadataLookupStr(&mdok, dbLookup, "GIVENDBCOL");
     303            // Values of the "where" columns
     304            const char *givenPS = psMetadataLookupStr(&mdok, dbLookup, "GIVENPS");
     305
     306            // Now, need to get the "given"s
     307            if (strlen(givenCols) > 0 || strlen(givenPS) > 0) {
     308                psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
     309                psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
     310                psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
     311                if (cols->n != values->n) {
     312                    psLogMsg(__func__, PS_LOG_WARN,
     313                             "The GIVENDBCOL and GIVENPS entries for %s do not have "
     314                             "the same number of entries --- ignored.\n", name);
     315                } else {
     316                    // Iterators for the lists
     317                    psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
     318                    psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
     319                    char *column = NULL;    // Name of the column
     320                    while ((column = psListGetAndIncrement(colsIter))) {
     321                        char *dependName = psListGetAndIncrement(valuesIter); // Name for the value
     322                        if (!strlen(column) || !strlen(name)) {
     323                            psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
     324                                     " empty --- ignored.\n", name);
     325                        } else {
     326                            // Search for the value name
     327                            psMetadataItem *item = NULL; // The value
     328                            if (!item && cell) {
     329                                item = psMetadataLookup(cell->concepts, dependName);
     330                            }
     331                            if (!item && chip) {
     332                                item = psMetadataLookup(chip->concepts, dependName);
     333                            }
     334                            if (!item && fpa) {
     335                                item = psMetadataLookup(fpa->concepts, dependName);
     336                            }
     337                            if (! item) {
     338                                psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB"
     339                                         " lookup on %s --- ignored.\n", dependName, name);
     340                            } else {
     341                                // We need to create a new psMetadataItem.  I don't think we can't
     342                                // simply hack the existing one, since that could conceivably cause
     343                                // memory leaks
     344                                psMetadataItem *newItem = psMetadataItemAlloc(name, item->type,
     345                                                          item->comment,
     346                                                          item->data.V);
     347                                psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
     348                                psFree(newItem);
     349                            }
     350                        }
     351                        psFree(dependName);
     352                        psFree(column);
     353                    } // Iterating through the columns
     354                    psFree(colsIter);
     355                    psFree(valuesIter);
     356
     357                    psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
     358                    // Note that we use limit=2 in order to test if there are multiple rows returned
     359
     360                    psMetadataItem *conceptItem = NULL; // The final result of the DB lookup
     361                    if (dbResult->n == 0) {
    291362                        psLogMsg(__func__, PS_LOG_WARN,
    292                                  "The GIVENDBCOL and GIVENPS entries for %s do not have "
    293                                  "the same number of entries --- ignored.\n", name);
     363                                 "Unable to find any rows in DB for %s --- ignored\n", name);
    294364                    } else {
    295                         // Iterators for the lists
    296                         psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
    297                         psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
    298                         char *column = NULL;    // Name of the column
    299                         while ((column = psListGetAndIncrement(colsIter))) {
    300                             char *dependName = psListGetAndIncrement(valuesIter); // Name for the value
    301                             if (!strlen(column) || !strlen(name)) {
    302                                 psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
    303                                          " empty --- ignored.\n", name);
    304                             } else {
    305                                 // Search for the value name
    306                                 psMetadataItem *item = NULL; // The value
    307                                 if (!item && cell) {
    308                                     item = psMetadataLookup(cell->concepts, dependName);
    309                                 }
    310                                 if (!item && chip) {
    311                                     item = psMetadataLookup(chip->concepts, dependName);
    312                                 }
    313                                 if (!item && fpa) {
    314                                     item = psMetadataLookup(fpa->concepts, dependName);
    315                                 }
    316                                 if (! item) {
    317                                     psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB"
    318                                              " lookup on %s --- ignored.\n", dependName, name);
    319                                 } else {
    320                                     // We need to create a new psMetadataItem.  I don't think we can't
    321                                     // simply hack the existing one, since that could conceivably cause
    322                                     // memory leaks
    323                                     psMetadataItem *newItem = psMetadataItemAlloc(name, item->type,
    324                                                               item->comment,
    325                                                               item->data.V);
    326                                     psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
    327                                     psFree(newItem);
    328                                 }
    329                             }
    330                             psFree(dependName);
    331                             psFree(column);
    332                         } // Iterating through the columns
    333                         psFree(colsIter);
    334                         psFree(valuesIter);
    335 
    336                         psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
    337                         // Note that we use limit=2 in order to test if there are multiple rows returned
    338 
    339                         psMetadataItem *conceptItem = NULL; // The final result of the DB lookup
    340                         if (dbResult->n == 0) {
     365                        if (dbResult-> n > 1) {
    341366                            psLogMsg(__func__, PS_LOG_WARN,
    342                                      "Unable to find any rows in DB for %s --- ignored\n", name);
    343                         } else {
    344                             if (dbResult-> n > 1) {
    345                                 psLogMsg(__func__, PS_LOG_WARN,
    346                                          "Multiple rows returned in DB lookup for %s --- "
    347                                          " using the first one only.\n", name);
    348                             }
    349                             conceptItem = (psMetadataItem*)dbResult->data[0];
     367                                     "Multiple rows returned in DB lookup for %s --- "
     368                                     " using the first one only.\n", name);
    350369                        }
    351 
    352                         // Now we have the result
    353                         conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
    354 
     370                        conceptItem = (psMetadataItem*)dbResult->data[0];
    355371                    }
    356                     psFree(cols);
    357                     psFree(values);
     372
     373                    // Now we have the result
     374                    conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
     375
    358376                }
    359             } // Doing the "given"s.
    360 
    361         } // Iterating through the concept specifications
    362         psFree(specsIter);
    363 
    364         return true;
    365     }
    366     return false;
     377                psFree(cols);
     378                psFree(values);
     379            }
     380        } // Doing the "given"s.
     381
     382    } // Iterating through the concept specifications
     383    psFree(specsIter);
     384
     385    return true;
    367386    #endif
    368387}
    369388
    370389
    371 
    372 
    373 #ifdef OLD
    374 
    375 psMetadataItem *pmConceptReadFromCamera(pmCell *cell, // The cell
    376                                         const char *concept // Name of concept
    377                                        )
    378 {
    379     if (cell) {
    380         psMetadata *camera = cell->config; // Camera configuration
    381         psMetadataItem *item = psMetadataLookup(camera, concept);
    382         return item;
    383     }
    384     return NULL;
    385 }
    386 
    387 psMetadataItem *pmConceptReadFromHeader(pmFPA *fpa, // The FPA that contains the chip
    388                                         pmChip *chip, // The chip that contains the cell
    389                                         pmCell *cell, // The cell
    390                                         const char *concept // Name of concept
    391                                        )
    392 {
    393     bool mdStatus = true;               // Status of MD lookup
    394     psMetadata *translation = psMetadataLookupMD(&mdStatus, fpa->camera, "TRANSLATION"); // FITS translation
    395     if (! mdStatus) {
    396         psError(PS_ERR_IO, false, "Unable to find TRANSLATION in camera configuration.\n");
    397         return NULL;
    398     }
    399 
    400     // Look for how to translate the concept into a FITS header name
    401     const char *keyword = psMetadataLookupStr(&mdStatus, translation, concept);
    402     if (mdStatus && strlen(keyword) > 0) {
    403         // We have a FITS header to look up --- search each level
    404         if (cell && cell->hdu) {
    405             psMetadataItem *cellItem = psMetadataLookup(cell->hdu->header, keyword);
    406             if (cellItem) {
    407                 // XXX: Need to clean up before returning
    408                 return cellItem;
    409             }
    410         }
    411 
    412         if (chip && chip->hdu) {
    413             psMetadataItem *chipItem = psMetadataLookup(chip->hdu->header, keyword);
    414             if (chipItem) {
    415                 // XXX: Need to clean up before returning
    416                 return chipItem;
    417             }
    418         }
    419 
    420         if (fpa->hdu) {
    421             psMetadataItem *fpaItem = psMetadataLookup(fpa->hdu->header, keyword);
    422             if (fpaItem) {
    423                 // XXX: Need to clean up before returning
    424                 return fpaItem;
    425             }
    426         }
    427     }
    428 
    429     // No header value
    430     return NULL;
    431 }
    432 
    433 
    434 // Look for a default
    435 psMetadataItem *pmConceptReadFromDefault(pmFPA *fpa, // The FPA that contains the chip
    436         pmChip *chip, // The chip that contains the cell
    437         pmCell *cell, // The cell
    438         const char *concept // Name of concept
    439                                         )
    440 {
    441     bool mdOK = true;                   // Status of MD lookup
    442     psMetadata *defaults = psMetadataLookupMD(&mdOK, fpa->camera, "DEFAULTS");
    443     if (! mdOK) {
    444         psError(PS_ERR_IO, false, "Unable to find DEFAULTS in camera configuration.\n");
    445         return NULL;
    446     }
    447 
    448     psMetadataItem *defItem = psMetadataLookup(defaults, concept);
    449     if (defItem) {
    450         if (defItem->type == PS_DATA_METADATA) {
    451             // A dependent default
    452             psTrace(__func__, 7, "Evaluating dependent default....\n");
    453             psMetadata *dependents = defItem->data.V; // The list of dependents
    454             // Find out what it depends on
    455             psString dependName = psStringCopy(concept);
    456             psStringAppend(&dependName, ".DEPEND");
    457             psString dependsOn = psMetadataLookupStr(&mdOK, defaults, dependName);
    458             if (! mdOK) {
    459                 psError(PS_ERR_IO, false, "Unable to find %s in camera configuration for dependent default"
    460                         " --- ignored\n", dependName);
    461                 // XXX: Need to clean up before returning
    462                 return NULL;
    463             }
    464             psFree(dependName);
    465             // Find the value of the dependent concept
    466             psMetadataItem *depItem = pmConceptReadFromHeader(fpa, chip, cell, dependsOn);
    467             if (! depItem) {
    468                 psError(PS_ERR_IO, true, "Unable to find value for %s (required for %s)\n", dependsOn,
    469                         concept);
    470                 return NULL;
    471             }
    472             if (depItem->type != PS_DATA_STRING) {
    473                 psError(PS_ERR_IO, true, "Value of %s is not of type string, as required for dependency"
    474                         " --- ignored.\n", dependsOn);
    475             }
    476 
    477             defItem = psMetadataLookup(dependents, depItem->data.V);    // This is now what we were after
    478         }
    479     }
    480 
    481     // XXX: Need to clean up before returning
    482     return defItem;                     // defItem is either NULL or points to what was desired
    483 }
    484 
    485 
    486 // Look for a database lookup
    487 // XXX: Not tested
    488 psMetadataItem *pmConceptReadFromDB(pmFPA *fpa, // The FPA that contains the chip
    489                                     pmChip *chip, // The chip that contains the cell
    490                                     pmCell *cell, // The cell
    491                                     psDB *db, // DB handle
    492                                     const char *concept // Name of concept
    493                                    )
    494 {
    495     if (! db) {
    496         // No database initialised
    497         return NULL;
    498     }
    499 
    500     bool mdStatus = true;               // Status of MD lookup
    501     psMetadata *database = psMetadataLookupMD(&mdStatus, fpa->camera, "DATABASE");
    502     if (! mdStatus) {
    503         // No error, because not everyone needs to use the DB
    504         return NULL;
    505     }
    506 
    507     psMetadata *dbLookup = psMetadataLookupMD(&mdStatus, database, concept);
    508     if (dbLookup) {
    509         const char *tableName = psMetadataLookupStr(&mdStatus, dbLookup, "TABLE"); // Name of the table
    510         // const char *colName = psMetadataLookupStr(&mdStatus, dbLookup, "COLUMN"); // Name of the column
    511         const char *givenCols = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENDBCOL"); // Name of "where"
    512         // columns
    513         const char *givenPS = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENPS"); // Values for "where"
    514         // columns
    515 
    516         // Now, need to get the "given"s
    517         if (strlen(givenCols) || strlen(givenPS)) {
    518             psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
    519             psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
    520             psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
    521             if (cols->n != values->n) {
    522                 psLogMsg(__func__, PS_LOG_WARN, "The GIVENDBCOL and GIVENPS entries for %s do not have "
    523                          "the same number of entries --- ignored.\n", concept);
    524             } else {
    525                 // Iterators for the lists
    526                 psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
    527                 psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
    528                 char *column = NULL;    // Name of the column
    529                 while ((column = psListGetAndIncrement(colsIter))) {
    530                     char *name = psListGetAndIncrement(valuesIter); // Name for the value
    531                     if (!strlen(column) || !strlen(name)) {
    532                         psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
    533                                  " empty --- ignored.\n", concept);
    534                     } else {
    535                         // Search for the value name
    536                         psMetadataItem *item = pmConceptReadFromHeader(fpa, chip, cell, name);
    537                         if (! item) {
    538                             item = pmConceptReadFromDefault(fpa, chip, cell, name);
    539                         }
    540                         if (! item) {
    541                             psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB "
    542                                      " lookup on %s --- ignored.\n", name, concept);
    543                         } else {
    544                             // We need to create a new psMetadataItem.  I don't think we can't simply hack
    545                             // the existing one, since that could conceivably cause memory leaks
    546                             psMetadataItem *newItem = psMetadataItemAlloc(concept, item->type,
    547                                                       item->comment, item->data.V);
    548                             psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
    549                             psFree(newItem);
    550                         }
    551                     }
    552                     psFree(name);
    553                     psFree(column);
    554                 } // Iterating through the columns
    555                 psFree(colsIter);
    556                 psFree(valuesIter);
    557 
    558                 psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
    559                 // Note that we use limit=2 in order to test if there are multiple rows returned
    560 
    561                 psMetadataItem *result = NULL; // The final result of the DB lookup
    562                 if (dbResult->n == 0) {
    563                     psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- ignored\n",
    564                              concept);
    565                 } else {
    566                     if (dbResult-> n > 1) {
    567                         psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s --- "
    568                                  " using the first one only.\n", concept);
    569                     }
    570                     result = (psMetadataItem*)dbResult->data[0];
    571                 }
    572                 // XXX: Need to clean up before returning
    573                 return result;
    574             }
    575             psFree(cols);
    576             psFree(values);
    577         }
    578     } // Doing the "given"s.
    579 
    580     psAbort(__func__, "Shouldn't ever get here.\n");
    581     return NULL;
    582 }
    583 
    584 
    585 // Concept lookup
    586 psMetadataItem *pmConceptRead(pmFPA *fpa, // The FPA
    587                               pmChip *chip,// The chip
    588                               pmCell *cell, // The cell
    589                               psDB *db, // DB handle
    590                               const char *name // Concept name
    591                              )
    592 {
    593     // Try headers, database, defaults in order
    594     psMetadataItem *item = pmConceptReadFromCamera(cell, name);
    595     if (! item) {
    596         item = pmConceptReadFromHeader(fpa, chip, cell, name);
    597     }
    598     if (! item) {
    599         item = pmConceptReadFromDB(fpa, chip, cell, db, name);
    600     }
    601     if (! item) {
    602         item = pmConceptReadFromDefault(fpa, chip, cell, name);
    603     }
    604     return item; // item is either NULL, or points to what was desired
    605 }
    606 
    607 
    608 #endif
  • trunk/psModules/src/concepts/pmConceptsStandard.c

    r7253 r7278  
    99#include "pmConceptsStandard.h"
    1010
     11// The functions in this file are intended to be called solely within the psModules concepts code.  For this
     12// reason, they use "assert" instead of the PS_ASSERT_WHATEVER functions --- if there's a problem, then
     13// there's a BIG problem that affects all of the code.
    1114
    1215#define COMPARE_REGIONS(a,b) (((a)->x0 == (b)->x0 && \
     
    3841
    3942// FPA.RA and FPA.DEC
    40 psMetadataItem *pmConceptParse_FPA_Coords(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     43psMetadataItem *p_pmConceptParse_FPA_Coords(psMetadataItem *concept,
     44        psMetadataItem *pattern,
     45        psMetadata *cameraFormat,
     46        pmFPA *fpa,
     47        pmChip *chip,
     48        pmCell *cell)
    4149{
    4250    assert(concept);
     
    102110
    103111// FPA.RA and FPA.DEC
    104 psMetadataItem *pmConceptFormat_FPA_Coords(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat)
    105 {
    106     assert(concept);
    107     assert(pattern);
     112psMetadataItem *p_pmConceptFormat_FPA_Coords(psMetadataItem *concept,
     113        psMetadata *cameraFormat,
     114        pmFPA *fpa,
     115        pmChip *chip,
     116        pmCell *cell)
     117{
     118    assert(concept);
    108119    assert(cameraFormat);
    109120
     
    112123    // How to interpret the coordinates
    113124    bool mdok = true;                   // Status of MD lookup
    114     psMetadata *formats = psMetadataLookupMD(&mdok, cameraFormat, "FORMATS");
     125    psMetadata *formats = psMetadataLookupMD(&mdok,
     126                          cameraFormat,
     127                          "FORMATS");
    115128    if (mdok && formats) {
    116         psString format = psMetadataLookupStr(&mdok, formats, pattern->name);
     129        psString format = psMetadataLookupStr(&mdok,formats, concept->name);
    117130        if (mdok && strlen(format) > 0) {
    118131            if (strcasecmp(format, "HOURS") == 0) {
     
    123136                // No action required
    124137            } else {
    125                 coords /= defaultCoordScaling(pattern);
     138                coords /= defaultCoordScaling(concept);
    126139            }
    127140        } else {
    128             coords /= defaultCoordScaling(pattern);
     141            coords /= defaultCoordScaling(concept);
    129142        }
    130143    } else {
    131         coords /= defaultCoordScaling(pattern);
     144        coords /= defaultCoordScaling(concept);
    132145    }
    133146
     
    140153    psString coordString = NULL;        // String with the coordinates in sexagesimal format
    141154    psStringAppend(&coordString, "%d:%d:%.2f", big, medium, small);
    142     psMetadataItem *coordItem = psMetadataItemAllocStr(pattern->name, pattern->comment, coordString);
     155    psMetadataItem *coordItem = psMetadataItemAllocStr(concept->name, concept->comment, coordString);
    143156    psFree(coordString);
    144157
     
    147160
    148161
    149 psMetadataItem *pmConceptParse_CELL_TRIMSEC(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     162psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(psMetadataItem *concept,
     163        psMetadataItem *pattern,
     164        psMetadata *cameraFormat,
     165        pmFPA *fpa,
     166        pmChip *chip,
     167        pmCell *cell)
    150168{
    151169    assert(concept);
     
    167185}
    168186
    169 psMetadataItem *pmConceptParse_CELL_BIASSEC(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     187psMetadataItem *p_pmConceptParse_CELL_BIASSEC(psMetadataItem *concept,
     188        psMetadataItem *pattern,
     189        psMetadata *cameraFormat,
     190        pmFPA *fpa,
     191        pmChip *chip,
     192        pmCell *cell)
    170193{
    171194    assert(concept);
     
    218241
    219242// CELL.XBIN and CELL.YBIN
    220 psMetadataItem *pmConceptParse_CELL_Binning(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     243psMetadataItem *p_pmConceptParse_CELL_Binning(psMetadataItem *concept,
     244        psMetadataItem *pattern,
     245        psMetadata *cameraFormat,
     246        pmFPA *fpa,
     247        pmChip *chip,
     248        pmCell *cell)
    221249{
    222250    assert(concept);
     
    249277
    250278
    251 psMetadataItem *pmConceptParse_CELL_TIMESYS(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     279psMetadataItem *p_pmConceptParse_CELL_TIMESYS(psMetadataItem *concept,
     280        psMetadataItem *pattern,
     281        psMetadata *cameraFormat,
     282        pmFPA *fpa,
     283        pmChip *chip,
     284        pmCell *cell)
    252285{
    253286    assert(concept);
     
    274307
    275308
    276 psMetadataItem *pmConceptParse_CELL_TIME(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     309psMetadataItem *p_pmConceptParse_CELL_TIME(psMetadataItem *concept,
     310        psMetadataItem *pattern,
     311        psMetadata *cameraFormat,
     312        pmFPA *fpa,
     313        pmChip *chip,
     314        pmCell *cell)
    277315{
    278316    assert(concept);
     
    466504}
    467505
    468 psMetadataItem *pmConceptParse_CELL_Positions(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     506psMetadataItem *p_pmConceptParse_CELL_Positions(psMetadataItem *concept,
     507        psMetadataItem *pattern,
     508        psMetadata *cameraFormat,
     509        pmFPA *fpa,
     510        pmChip *chip,
     511        pmCell *cell)
    469512{
    470513    assert(concept);
     
    489532
    490533
    491 psMetadataItem *pmConceptFormat_CELL_TRIMSEC(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     534psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(psMetadataItem *concept,
     535        psMetadata *cameraFormat,
     536        pmFPA *fpa,
     537        pmChip *chip,
     538        pmCell *cell)
    492539{
    493540    assert(concept);
     
    501548}
    502549
    503 psMetadataItem *pmConceptFormat_CELL_BIASSEC(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     550psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(psMetadataItem *concept,
     551        psMetadata *cameraFormat,
     552        pmFPA *fpa,
     553        pmChip *chip,
     554        pmCell *cell)
    504555{
    505556    // Return a metadata item containing a list of metadata items of region strings
     
    523574// This function actually does both CELL.XBIN and CELL.YBIN if CELL.XBIN and CELL.YBIN are specified by the
    524575// same header.
    525 psMetadataItem *pmConceptFormat_CELL_XBIN(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     576psMetadataItem *p_pmConceptFormat_CELL_XBIN(psMetadataItem *concept,
     577        psMetadata *cameraFormat,
     578        pmFPA *fpa,
     579        pmChip *chip,
     580        pmCell *cell)
    526581{
    527582    assert(concept);
     
    546601
    547602// Only need to format if both if CELL.XBIN and CELL.YBIN are not specified by the same header.
    548 psMetadataItem *pmConceptFormat_CELL_YBIN(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     603psMetadataItem *p_pmConceptFormat_CELL_YBIN(psMetadataItem *concept,
     604        psMetadata *cameraFormat,
     605        pmFPA *fpa,
     606        pmChip *chip,
     607        pmCell *cell)
    549608{
    550609    assert(concept);
     
    565624
    566625
    567 psMetadataItem *pmConceptFormat_CELL_TIMESYS(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     626psMetadataItem *p_pmConceptFormat_CELL_TIMESYS(psMetadataItem *concept,
     627        psMetadata *cameraFormat,
     628        pmFPA *fpa,
     629        pmChip *chip,
     630        pmCell *cell)
    568631{
    569632    psString sys = NULL;            // String to store
     
    590653}
    591654
    592 psMetadataItem *pmConceptFormat_CELL_TIME(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     655psMetadataItem *p_pmConceptFormat_CELL_TIME(psMetadataItem *concept,
     656        psMetadata *cameraFormat,
     657        pmFPA *fpa,
     658        pmChip *chip,
     659        pmCell *cell)
    593660{
    594661    psTime *time = concept->data.V;     // The time
     
    699766}
    700767
    701 psMetadataItem *pmConceptFormat_CELL_Positions(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell)
     768psMetadataItem *p_pmConceptFormat_CELL_Positions(psMetadataItem *concept,
     769        psMetadata *cameraFormat,
     770        pmFPA *fpa,
     771        pmChip *chip,
     772        pmCell *cell)
    702773{
    703774    assert(concept);
  • trunk/psModules/src/concepts/pmConceptsStandard.h

    r7017 r7278  
    55#include "pmFPA.h"
    66
     7// Functions to parse and format the standard concepts
    78
    8 psMetadataItem *pmConceptParse_FPA_Coords(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    9 psMetadataItem *pmConceptFormat_FPA_Coords(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat);
    10 psMetadataItem *pmConceptParse_CELL_TRIMSEC(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    11 psMetadataItem *pmConceptParse_CELL_BIASSEC(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    12 psMetadataItem *pmConceptParse_CELL_Binning(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    13 psMetadataItem *pmConceptParse_CELL_TIMESYS(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    14 psMetadataItem *pmConceptParse_CELL_TIME(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    15 psMetadataItem *pmConceptParse_CELL_Positions(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    16 psMetadataItem *pmConceptFormat_CELL_TRIMSEC(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    17 psMetadataItem *pmConceptFormat_CELL_BIASSEC(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    18 psMetadataItem *pmConceptFormat_CELL_XBIN(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    19 psMetadataItem *pmConceptFormat_CELL_YBIN(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    20 psMetadataItem *pmConceptFormat_CELL_TIMESYS(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    21 psMetadataItem *pmConceptFormat_CELL_TIME(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
    22 psMetadataItem *pmConceptFormat_CELL_Positions(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
     9psMetadataItem *p_pmConceptParse_FPA_Coords(psMetadataItem *concept,
     10        psMetadataItem *pattern,
     11        psMetadata *cameraFormat,
     12        pmFPA *fpa,
     13        pmChip *chip,
     14        pmCell *cell);
     15psMetadataItem *p_pmConceptFormat_FPA_Coords(psMetadataItem *concept,
     16        psMetadata *cameraFormat,
     17        pmFPA *fpa,
     18        pmChip *chip,
     19        pmCell *cell);
     20psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(psMetadataItem *concept,
     21        psMetadataItem *pattern,
     22        psMetadata *cameraFormat,
     23        pmFPA *fpa,
     24        pmChip *chip,
     25        pmCell *cell);
     26psMetadataItem *p_pmConceptParse_CELL_BIASSEC(psMetadataItem *concept,
     27        psMetadataItem *pattern,
     28        psMetadata *cameraFormat,
     29        pmFPA *fpa,
     30        pmChip *chip,
     31        pmCell *cell);
     32psMetadataItem *p_pmConceptParse_CELL_Binning(psMetadataItem *concept,
     33        psMetadataItem *pattern,
     34        psMetadata *cameraFormat,
     35        pmFPA *fpa,
     36        pmChip *chip,
     37        pmCell *cell);
     38psMetadataItem *p_pmConceptParse_CELL_TIMESYS(psMetadataItem *concept,
     39        psMetadataItem *pattern,
     40        psMetadata *cameraFormat,
     41        pmFPA *fpa,
     42        pmChip *chip,
     43        pmCell *cell);
     44psMetadataItem *p_pmConceptParse_CELL_TIME(psMetadataItem *concept,
     45        psMetadataItem *pattern,
     46        psMetadata *cameraFormat,
     47        pmFPA *fpa,
     48        pmChip *chip,
     49        pmCell *cell);
     50psMetadataItem *p_pmConceptParse_CELL_Positions(psMetadataItem *concept,
     51        psMetadataItem *pattern,
     52        psMetadata *cameraFormat,
     53        pmFPA *fpa,
     54        pmChip *chip,
     55        pmCell *cell);
     56psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(psMetadataItem *concept,
     57        psMetadata *cameraFormat,
     58        pmFPA *fpa,
     59        pmChip *chip,
     60        pmCell *cell);
     61psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(psMetadataItem *concept,
     62        psMetadata *cameraFormat,
     63        pmFPA *fpa,
     64        pmChip *chip,
     65        pmCell *cell);
     66psMetadataItem *p_pmConceptFormat_CELL_XBIN(psMetadataItem *concept,
     67        psMetadata *cameraFormat,
     68        pmFPA *fpa,
     69        pmChip *chip,
     70        pmCell *cell);
     71psMetadataItem *p_pmConceptFormat_CELL_YBIN(psMetadataItem *concept,
     72        psMetadata *cameraFormat,
     73        pmFPA *fpa,
     74        pmChip *chip,
     75        pmCell *cell);
     76psMetadataItem *p_pmConceptFormat_CELL_TIMESYS(psMetadataItem *concept,
     77        psMetadata *cameraFormat,
     78        pmFPA *fpa,
     79        pmChip *chip,
     80        pmCell *cell);
     81psMetadataItem *p_pmConceptFormat_CELL_TIME(psMetadataItem *concept,
     82        psMetadata *cameraFormat,
     83        pmFPA *fpa,
     84        pmChip *chip,
     85        pmCell *cell);
     86psMetadataItem *p_pmConceptFormat_CELL_Positions(psMetadataItem *concept,
     87        psMetadata *cameraFormat,
     88        pmFPA *fpa,
     89        pmChip *chip,
     90        pmCell *cell);
    2391
    2492#endif
  • trunk/psModules/src/concepts/pmConceptsWrite.c

    r7017 r7278  
    11#include <stdio.h>
     2#include <assert.h>
    23#include <strings.h>
    34#include "pslib.h"
     
    110111                                    )
    111112{
     113    assert(spec);
     114    assert(cameraFormat);
     115
    112116    if (concept) {
    113117        psMetadataItem *formatted = NULL;  // The formatted concept
     
    129133                             )
    130134{
     135    assert(hdu);
     136    assert(keyword && strlen(keyword) > 0);
     137    assert(item);
     138
    131139    if (!hdu->header) {
    132140        return false;
     
    166174                       )
    167175{
     176    assert(hdu);
     177    assert(keywords);
     178    assert(item);
     179
    168180    bool status = true;                 // Status of writing headers, to be returned
    169181    if (item->type == PS_DATA_LIST) {
     
    204216                            )
    205217{
    206     if (cell) {
    207         pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
    208         if (!hdu) {
    209             return false;
    210         }
    211         psMetadata *cameraFormat = hdu->format; // The camera format
    212         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    213         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    214         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    215             pmConceptSpec *spec = specItem->data.V; // The specification
    216             psString name = specItem->name; // The concept name
    217             psMetadataItem *cameraItem = psMetadataLookup(cell->config, name); // The concept from the camera,
    218             // or NULL
    219             if (cameraItem) {
    220                 // Grab the concept
    221                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The concept
    222                 // Formatted version
    223                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, NULL, NULL, cell);
    224                 if (!formatted) {
    225                     continue;
    226                 }
    227                 psString nameSource = NULL; // String with the concept name and ".SOURCE" added
    228                 psStringAppend(&nameSource, "%s.SOURCE", name);
    229                 bool mdok = true;       // Status of MD lookup
    230                 psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
    231                 if (mdok && strlen(source) > 0) {
    232                     psTrace(__func__, 8, "%s is %s\n", nameSource, source);
    233                     if (strcasecmp(source, "HEADER") == 0) {
    234                         if (cameraItem->type != PS_DATA_STRING) {
    235                             psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by header, but is not "
    236                                      "of type STR --- ignored.\n", conceptItem->name);
    237                             continue;
    238                         }
    239                         psTrace(__func__, 8, "Writing %s to header %s\n", name, cameraItem->data.V);
    240                         writeHeader(hdu, cameraItem->data.V, formatted);
    241                     } else if (strcasecmp(source, "VALUE") == 0) {
    242                         psTrace(__func__, 8, "Checking %s against camera format.\n", name);
    243                         if (! compareConcepts(formatted, cameraItem)) {
    244                             psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by value in the camera "
    245                                      "format, but the values don't match.\n", name);
    246                         }
    247                     } else {
    248                         psLogMsg(__func__, PS_LOG_WARN, "Concept source %s isn't HEADER or VALUE --- can't "
    249                                  "write\n", nameSource);
     218    PS_ASSERT_PTR_NON_NULL(specs, false);
     219    PS_ASSERT_PTR_NON_NULL(concepts, false);
     220    if (!cell) {
     221        return false;
     222    }
     223
     224    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
     225    if (!hdu) {
     226        return false;
     227    }
     228    psMetadata *cameraFormat = hdu->format; // The camera format
     229    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     230    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     231    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     232        pmConceptSpec *spec = specItem->data.V; // The specification
     233        psString name = specItem->name; // The concept name
     234        psMetadataItem *cameraItem = psMetadataLookup(cell->config, name); // The concept from the camera,
     235        // or NULL
     236        if (cameraItem) {
     237            // Grab the concept
     238            psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The concept
     239            // Formatted version
     240            psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, NULL, NULL, cell);
     241            if (!formatted) {
     242                continue;
     243            }
     244            psString nameSource = NULL; // String with the concept name and ".SOURCE" added
     245            psStringAppend(&nameSource, "%s.SOURCE", name);
     246            bool mdok = true;       // Status of MD lookup
     247            psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
     248            if (mdok && strlen(source) > 0) {
     249                psTrace(__func__, 8, "%s is %s\n", nameSource, source);
     250                if (strcasecmp(source, "HEADER") == 0) {
     251                    if (cameraItem->type != PS_DATA_STRING) {
     252                        psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by header, but is not "
     253                                 "of type STR --- ignored.\n", conceptItem->name);
     254                        continue;
    250255                    }
    251                 } else if (! compareConcepts(formatted, cameraItem)) {
    252                     // Assume it's specified by value
    253                     psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by value in the camera "
    254                              "format, but the values don't match.\n", name);
    255                 }
    256                 psFree(formatted);
    257                 psFree(nameSource);
    258             }
    259 
    260         }
    261         psFree(specsIter);
    262         return true;
    263     }
    264     return false;
     256                    psTrace(__func__, 8, "Writing %s to header %s\n", name, cameraItem->data.V);
     257                    writeHeader(hdu, cameraItem->data.V, formatted);
     258                } else if (strcasecmp(source, "VALUE") == 0) {
     259                    psTrace(__func__, 8, "Checking %s against camera format.\n", name);
     260                    if (! compareConcepts(formatted, cameraItem)) {
     261                        psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by value in the camera "
     262                                 "format, but the values don't match.\n", name);
     263                    }
     264                } else {
     265                    psLogMsg(__func__, PS_LOG_WARN, "Concept source %s isn't HEADER or VALUE --- can't "
     266                             "write\n", nameSource);
     267                }
     268            } else if (! compareConcepts(formatted, cameraItem)) {
     269                // Assume it's specified by value
     270                psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by value in the camera "
     271                         "format, but the values don't match.\n", name);
     272            }
     273            psFree(formatted);
     274            psFree(nameSource);
     275        }
     276
     277    }
     278    psFree(specsIter);
     279    return true;
    265280}
    266281
     
    272287                              )
    273288{
     289    PS_ASSERT_PTR_NON_NULL(specs, false);
     290    PS_ASSERT_PTR_NON_NULL(concepts, false);
     291
    274292    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
    275293    if (!hdu) {
     
    279297    bool mdok = true;                   // Status of MD lookup
    280298    psMetadata *defaults = psMetadataLookupMD(&mdok, cameraFormat, "DEFAULTS"); // The DEFAULTS spec
    281     if (mdok && defaults) {
    282         pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    283         psMetadata *cameraFormat = hdu->format; // The camera format
    284         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    285         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    286         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    287             pmConceptSpec *spec = specItem->data.V; // The specification
    288             psString name = specItem->name; // The concept name
    289             psMetadataItem *defaultItem = psMetadataLookup(defaults, name); // The item from the DEFAULTS
    290             if (defaultItem) {
    291                 psMetadataItem *conceptItem = NULL; // The item from the concepts
    292                 if (defaultItem->type == PS_DATA_METADATA) {
    293                     // It's a menu --- need to look up the .DEPEND
    294                     psString dependName = NULL; // The concept name with ".DEPEND" on the end
    295                     psStringAppend(&dependName, ".DEPEND");
    296                     psString dependKey = psMetadataLookupStr(&mdok, defaults, dependName); // The keyword
    297                     psFree(dependName);
    298                     if (!mdok || !dependKey || strlen(dependKey) == 0) {
    299                         psLogMsg(__func__, PS_LOG_WARN, "Can't find %s in the DEFAULTS for %s --- ignored.\n",
    300                                  dependName, name);
    301                         continue;
    302                     }
    303                     psString dependValue = psMetadataLookupStr(&mdok, concepts, dependName); // The value
    304                     if (!mdok || !dependKey || strlen(dependKey) == 0) {
    305                         psLogMsg(__func__, PS_LOG_WARN, "Concept %s specified by %s isn't of type STR -- "
    306                                  "ignored.\n", name, dependName);
    307                         continue;
    308                     }
    309                     conceptItem = psMetadataLookup(defaultItem->data.V, dependValue);
    310                 } else {
    311                     conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
    312                 }
    313                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
    314                 if (!formatted) {
     299    if (!mdok || !defaults) {
     300        return false;
     301    }
     302
     303    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     304    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     305    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     306        pmConceptSpec *spec = specItem->data.V; // The specification
     307        psString name = specItem->name; // The concept name
     308        psMetadataItem *defaultItem = psMetadataLookup(defaults, name); // The item from the DEFAULTS
     309        if (defaultItem) {
     310            psMetadataItem *conceptItem = NULL; // The item from the concepts
     311            if (defaultItem->type == PS_DATA_METADATA) {
     312                // It's a menu --- need to look up the .DEPEND
     313                psString dependName = NULL; // The concept name with ".DEPEND" on the end
     314                psStringAppend(&dependName, ".DEPEND");
     315                psString dependKey = psMetadataLookupStr(&mdok, defaults, dependName); // The keyword
     316                psFree(dependName);
     317                if (!mdok || !dependKey || strlen(dependKey) == 0) {
     318                    psLogMsg(__func__, PS_LOG_WARN, "Can't find %s in the DEFAULTS for %s --- ignored.\n",
     319                             dependName, name);
    315320                    continue;
    316321                }
    317                 if (! compareConcepts(formatted, defaultItem)) {
    318                     psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by the DEFAULTS in the camera "
    319                              "format, but the values don't match.\n", name);
    320                 }
    321                 psFree(formatted);
    322             }
    323         }
    324         psFree(specsIter);
    325         return true;
    326     }
    327     return false;
     322                psString dependValue = psMetadataLookupStr(&mdok, concepts, dependName); // The value
     323                if (!mdok || !dependKey || strlen(dependKey) == 0) {
     324                    psLogMsg(__func__, PS_LOG_WARN, "Concept %s specified by %s isn't of type STR -- "
     325                             "ignored.\n", name, dependName);
     326                    continue;
     327                }
     328                conceptItem = psMetadataLookup(defaultItem->data.V, dependValue);
     329            } else {
     330                conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
     331            }
     332            psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
     333            if (!formatted) {
     334                continue;
     335            }
     336            if (! compareConcepts(formatted, defaultItem)) {
     337                psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by the DEFAULTS in the camera "
     338                         "format, but the values don't match.\n", name);
     339            }
     340            psFree(formatted);
     341        }
     342    }
     343    psFree(specsIter);
     344    return true;
    328345}
    329346
     
    336353                            )
    337354{
     355    PS_ASSERT_PTR_NON_NULL(specs, false);
     356    PS_ASSERT_PTR_NON_NULL(concepts, false);
     357
    338358    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
    339359    if (!hdu) {
     
    343363    bool mdok = true;                   // Status of MD lookup
    344364    psMetadata *translation = psMetadataLookupMD(&mdok, cameraFormat, "TRANSLATION"); // The TRANSLATION spec
    345     if (mdok && translation) {
    346         pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    347         psMetadata *cameraFormat = hdu->format; // The camera format
    348         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    349         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    350         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    351             pmConceptSpec *spec = specItem->data.V; // The specification
    352             psString name = specItem->name; // The concept name
    353             psMetadataItem *headerItem = psMetadataLookup(translation, name); // The item from the TRANSLATION
    354             if (headerItem) {
    355                 if (headerItem->type != PS_DATA_STRING) {
    356                     psLogMsg(__func__, PS_LOG_WARN, "TRANSLATION keyword for concept %s isn't of type STR ---"
    357                              " ignored.", name);
    358                     continue;
    359                 }
    360                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
    361                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
    362                 if (!formatted) {
    363                     continue;
    364                 }
    365                 psList *keywords = psStringSplit(headerItem->data.V, " ,;", true); // List of header keywords
    366                 if (formatted->type == PS_DATA_LIST) {
    367                     psList *values = formatted->data.V; // The values for the headers
    368                     if (values->n != keywords->n) {
    369                         psLogMsg(__func__, PS_LOG_WARN, "Number of headers specified does not match number "
    370                                  "of values for concept %s.\n", name);
     365    if (!mdok || !translation) {
     366        return false;
     367    }
     368
     369    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     370    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     371    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     372        pmConceptSpec *spec = specItem->data.V; // The specification
     373        psString name = specItem->name; // The concept name
     374        psMetadataItem *headerItem = psMetadataLookup(translation, name); // The item from the TRANSLATION
     375        if (headerItem) {
     376            if (headerItem->type != PS_DATA_STRING) {
     377                psLogMsg(__func__, PS_LOG_WARN, "TRANSLATION keyword for concept %s isn't of type STR ---"
     378                         " ignored.", name);
     379                continue;
     380            }
     381            psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
     382            psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
     383            if (!formatted) {
     384                continue;
     385            }
     386            psList *keywords = psStringSplit(headerItem->data.V, " ,;", true); // List of header keywords
     387            if (formatted->type == PS_DATA_LIST) {
     388                psList *values = formatted->data.V; // The values for the headers
     389                if (values->n != keywords->n) {
     390                    psLogMsg(__func__, PS_LOG_WARN, "Number of headers specified does not match number "
     391                             "of values for concept %s.\n", name);
     392                }
     393                psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); // Iterator
     394                psListIterator *keywordsIter = psListIteratorAlloc(keywords, PS_LIST_HEAD, false);
     395                psMetadataItem *valuesItem = NULL; // Item from list
     396                while ((valuesItem = psListGetAndIncrement(valuesIter))) {
     397                    psString keyword = psListGetAndIncrement(keywordsIter); // Keyword from the list
     398                    if (strlen(keyword) > 0) {
     399                        writeHeader(hdu, keyword, formatted);
    371400                    }
    372                     psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); // Iterator
    373                     psListIterator *keywordsIter = psListIteratorAlloc(keywords, PS_LIST_HEAD, false);
    374                     psMetadataItem *valuesItem = NULL; // Item from list
    375                     while ((valuesItem = psListGetAndIncrement(valuesIter))) {
    376                         psString keyword = psListGetAndIncrement(keywordsIter); // Keyword from the list
    377                         if (strlen(keyword) > 0) {
    378                             writeHeader(hdu, keyword, formatted);
    379                         }
    380                     }
    381                     psFree(valuesIter);
    382                     psFree(keywordsIter);
    383                 } else {
    384                     psString keyword = psListGet(keywords, PS_LIST_HEAD); // The keyword
    385                     writeHeader(hdu, keyword, formatted);
    386                 }
    387                 psFree(formatted);
    388                 psFree(keywords);
    389             }
    390         }
    391         psFree(specsIter);
    392         return true;
    393     }
    394     return false;
     401                }
     402                psFree(valuesIter);
     403                psFree(keywordsIter);
     404            } else {
     405                psString keyword = psListGet(keywords, PS_LIST_HEAD); // The keyword
     406                writeHeader(hdu, keyword, formatted);
     407            }
     408            psFree(formatted);
     409            psFree(keywords);
     410        }
     411    }
     412    psFree(specsIter);
     413    return true;
    395414}
    396415
     
    404423                              )
    405424{
     425    PS_ASSERT_PTR_NON_NULL(specs, false);
     426    PS_ASSERT_PTR_NON_NULL(concepts, false);
     427
     428    if (!db) {
     429        return false;
     430    }
     431
    406432    #ifdef OMIT_PSDB
    407433    return false;
     
    415441    bool mdok = true;                   // Status of MD lookup
    416442    psMetadata *database = psMetadataLookupMD(&mdok, cameraFormat, "DATABASE"); // The DATABASE spec
    417     if (mdok && database) {
    418         pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
    419         psMetadata *cameraFormat = hdu->format; // The camera format
    420         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
    421         psMetadataItem *specItem = NULL;    // Item from the specs metadata
    422         while ((specItem = psMetadataGetAndIncrement(specsIter))) {
    423             pmConceptSpec *spec = specItem->data.V; // The specification
    424             psString name = specItem->name; // The concept name
    425 
    426             psMetadataItem *dbItem = psMetadataLookup(database, name); // The item from the DATABASE
    427             if (dbItem) {
    428                 if (dbItem->type != PS_DATA_METADATA) {
    429                     psLogMsg(__func__, PS_LOG_WARN, "DATABASE keyword for concept %s isn't of type METADATA "
    430                              "--- ignored.\n", name);
    431                     continue;
    432                 }
    433 
    434                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
    435                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
    436                 if (!formatted) {
    437                     continue;
    438                 }
    439 
    440                 psMetadata *dbLookup = dbItem->data.V; // How to look up the value of interest
    441                 // Name of the table
    442                 const char *tableName = psMetadataLookupStr(&mdok, dbLookup, "TABLE");
    443                 // Name of "where" columns
    444                 const char *givenCols = psMetadataLookupStr(&mdok, dbLookup, "GIVENDBCOL");
    445                 // Values for "where" columns
    446                 const char *givenPS = psMetadataLookupStr(&mdok, dbLookup, "GIVENPS");
    447 
    448                 // Now, need to get the "given"s
    449                 if (strlen(givenCols) || strlen(givenPS)) {
    450                     psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
    451                     psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
    452                     psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
    453                     if (cols->n != values->n) {
    454                         psLogMsg(__func__, PS_LOG_WARN,
    455                                  "The GIVENDBCOL and GIVENPS entries for %s do not have "
    456                                  "the same number of entries --- ignored.\n", name);
     443    if (!mdok || !database) {
     444        return false;
     445    }
     446    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     447    psMetadataItem *specItem = NULL;    // Item from the specs metadata
     448    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     449        pmConceptSpec *spec = specItem->data.V; // The specification
     450        psString name = specItem->name; // The concept name
     451
     452        psMetadataItem *dbItem = psMetadataLookup(database, name); // The item from the DATABASE
     453        if (dbItem) {
     454            if (dbItem->type != PS_DATA_METADATA) {
     455                psLogMsg(__func__, PS_LOG_WARN, "DATABASE keyword for concept %s isn't of type METADATA "
     456                         "--- ignored.\n", name);
     457                continue;
     458            }
     459
     460            psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
     461            psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
     462            if (!formatted) {
     463                continue;
     464            }
     465
     466            psMetadata *dbLookup = dbItem->data.V; // How to look up the value of interest
     467            // Name of the table
     468            const char *tableName = psMetadataLookupStr(&mdok, dbLookup, "TABLE");
     469            // Name of "where" columns
     470            const char *givenCols = psMetadataLookupStr(&mdok, dbLookup, "GIVENDBCOL");
     471            // Values for "where" columns
     472            const char *givenPS = psMetadataLookupStr(&mdok, dbLookup, "GIVENPS");
     473
     474            // Now, need to get the "given"s
     475            if (strlen(givenCols) || strlen(givenPS)) {
     476                psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
     477                psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
     478                psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
     479                if (cols->n != values->n) {
     480                    psLogMsg(__func__, PS_LOG_WARN,
     481                             "The GIVENDBCOL and GIVENPS entries for %s do not have "
     482                             "the same number of entries --- ignored.\n", name);
     483                } else {
     484                    // Iterators for the lists
     485                    psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
     486                    psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
     487                    char *column = NULL;    // Name of the column
     488                    while ((column = psListGetAndIncrement(colsIter))) {
     489                        char *dependName = psListGetAndIncrement(valuesIter); // Name for the value
     490                        if (!strlen(column) || !strlen(name)) {
     491                            psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
     492                                     " empty --- ignored.\n", name);
     493                        } else {
     494                            // Search for the value name
     495                            psMetadataItem *item = NULL; // The value
     496                            if (!item && cell) {
     497                                item = psMetadataLookup(cell->concepts, dependName);
     498                            }
     499                            if (!item && chip) {
     500                                item = psMetadataLookup(chip->concepts, dependName);
     501                            }
     502                            if (!item && fpa) {
     503                                item = psMetadataLookup(fpa->concepts, dependName);
     504                            }
     505                            if (! item) {
     506                                psLogMsg(__func__, PS_LOG_ERROR,
     507                                         "Unable to find the value name %s for DB "
     508                                         " lookup on %s --- ignored.\n", dependName, name);
     509                            } else {
     510                                // We need to create a new psMetadataItem.  I don't think we can't simply
     511                                // hack the existing one, since that could conceivably cause memory leaks
     512                                psMetadataAddItem(selection, formatted, PS_LIST_TAIL, PS_META_REPLACE);
     513                                psFree(formatted);
     514                            }
     515                        }
     516                        psFree(dependName);
     517                        psFree(column);
     518                    } // Iterating through the columns
     519                    psFree(colsIter);
     520                    psFree(valuesIter);
     521
     522                    // Check first to make sure we're only going to touch one row
     523                    psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
     524                    // Note that we use limit=2 in order to test if there are multiple rows returned
     525                    if (! dbResult || dbResult->n == 0) {
     526                        psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- "
     527                                 "ignored\n", name);
     528                        return false;
    457529                    } else {
    458                         // Iterators for the lists
    459                         psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
    460                         psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
    461                         char *column = NULL;    // Name of the column
    462                         while ((column = psListGetAndIncrement(colsIter))) {
    463                             char *dependName = psListGetAndIncrement(valuesIter); // Name for the value
    464                             if (!strlen(column) || !strlen(name)) {
    465                                 psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
    466                                          " empty --- ignored.\n", name);
    467                             } else {
    468                                 // Search for the value name
    469                                 psMetadataItem *item = NULL; // The value
    470                                 if (!item && cell) {
    471                                     item = psMetadataLookup(cell->concepts, dependName);
    472                                 }
    473                                 if (!item && chip) {
    474                                     item = psMetadataLookup(chip->concepts, dependName);
    475                                 }
    476                                 if (!item && fpa) {
    477                                     item = psMetadataLookup(fpa->concepts, dependName);
    478                                 }
    479                                 if (! item) {
    480                                     psLogMsg(__func__, PS_LOG_ERROR,
    481                                              "Unable to find the value name %s for DB "
    482                                              " lookup on %s --- ignored.\n", dependName, name);
    483                                 } else {
    484                                     // We need to create a new psMetadataItem.  I don't think we can't simply
    485                                     // hack the existing one, since that could conceivably cause memory leaks
    486                                     psMetadataAddItem(selection, formatted, PS_LIST_TAIL, PS_META_REPLACE);
    487                                     psFree(formatted);
    488                                 }
    489                             }
    490                             psFree(dependName);
    491                             psFree(column);
    492                         } // Iterating through the columns
    493                         psFree(colsIter);
    494                         psFree(valuesIter);
    495 
    496                         // Check first to make sure we're only going to touch one row
    497                         psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
    498                         // Note that we use limit=2 in order to test if there are multiple rows returned
    499                         if (! dbResult || dbResult->n == 0) {
    500                             psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- "
    501                                      "ignored\n", name);
    502                             return false;
    503                         } else {
    504                             if (dbResult->n > 1) {
    505                                 psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s "
    506                                          "--- ignored.\n", name);
    507                             }
    508                             // Update the DB
    509                             psMetadata *update = psMetadataAlloc();
    510                             psMetadataAddItem(update, conceptItem, PS_LIST_HEAD, 0);
    511                             psDBUpdateRows(db, tableName, selection, update);
    512                             psFree(update);
    513                             return true;
     530                        if (dbResult->n > 1) {
     531                            psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s "
     532                                     "--- ignored.\n", name);
    514533                        }
     534                        // Update the DB
     535                        psMetadata *update = psMetadataAlloc();
     536                        psMetadataAddItem(update, conceptItem, PS_LIST_HEAD, 0);
     537                        psDBUpdateRows(db, tableName, selection, update);
     538                        psFree(update);
     539                        return true;
    515540                    }
    516                     psFree(cols);
    517                     psFree(values);
    518                 } // Doing the "given"s.
    519             }
    520         }
    521         psFree(specsIter);
    522         return true;
    523     }
    524     return false;
     541                }
     542                psFree(cols);
     543                psFree(values);
     544            } // Doing the "given"s.
     545        }
     546    }
     547    psFree(specsIter);
     548    return true;
    525549    #endif
    526550}
    527551
    528 
    529 
    530 
    531 #if 0
    532 
    533 // Well, not really "write", but check to make sure it's there and matches
    534 bool pmConceptWriteToCamera(pmCell *cell, // The cell
    535                             psMetadataItem *concept // Concept
    536                            )
    537 {
    538     if (! cell->config) {
    539         return false;
    540     }
    541     if (cell) {
    542         psMetadataItem *item = psMetadataLookup(cell->config, concept->name); // Info we want
    543         return compareConcepts(item, concept);
    544     }
    545 
    546     return false;
    547 }
    548 
    549 // Write the concept to the header in the appropriate location
    550 bool pmConceptWriteToHeader(pmFPA *fpa, // The FPA that contains the chip
    551                             pmChip *chip, // The chip that contains the cell
    552                             pmCell *cell, // The cell
    553                             psMetadataItem *concept // Concept
    554                            )
    555 {
    556     bool mdok = true;                   // Status of MD lookup
    557     bool status = false;                // Status of setting header
    558     if (! fpa->camera) {
    559         return false;
    560     }
    561     psMetadata *translation = psMetadataLookupMD(&mdok, fpa->camera, "TRANSLATION"); // FITS translation
    562     if (! mdok) {
    563         psError(PS_ERR_IO, false, "Unable to find TRANSLATION in camera configuration.\n");
    564         return false;
    565     }
    566 
    567     // Look for how to translate the concept into a FITS header name
    568     const char *keyword = psMetadataLookupStr(&mdok, translation, concept->name);
    569     if (mdok && strlen(keyword) > 0) {
    570         psTrace(__func__, 6, "It's in keyword %s\n", keyword);
    571         psMetadataItem *headerItem = NULL; // Item to add to header
    572         // XXX: Need to expand range of types
    573         switch (concept->type) {
    574         case PS_DATA_STRING:
    575             headerItem = psMetadataItemAllocStr(keyword, concept->comment, concept->data.V);
    576             break;
    577         case PS_DATA_S32:
    578             headerItem = psMetadataItemAllocS32(keyword, concept->comment, concept->data.S32);
    579             break;
    580         case PS_DATA_F32:
    581             headerItem = psMetadataItemAllocF32(keyword, concept->comment, concept->data.F32);
    582             break;
    583         case PS_DATA_F64:
    584             headerItem = psMetadataItemAllocF64(keyword, concept->comment, concept->data.F64);
    585             break;
    586         default:
    587             headerItem = psMetadataItemAlloc(keyword, concept->type, concept->comment,
    588                                              concept->data.V); // Item for the header
    589         }
    590 
    591         // We have a FITS header to look up --- search each level
    592         if (cell && cell->hdu) {
    593             psTrace(__func__, 7, "Adding to the cell level header...\n");
    594             psMetadataAddItem(cell->hdu->header, headerItem, PS_LIST_TAIL, PS_META_REPLACE);
    595             status = true;
    596         } else if (chip && chip->hdu) {
    597             psTrace(__func__, 7, "Adding to the chip level header...\n");
    598             psMetadataAddItem(chip->hdu->header, headerItem, PS_LIST_TAIL, PS_META_REPLACE);
    599             status = true;
    600         } else if (fpa->hdu) {
    601             psTrace(__func__, 7, "Adding to the FPA level header...\n");
    602             psMetadataAddItem(fpa->hdu->header, headerItem, PS_LIST_TAIL, PS_META_REPLACE);
    603             status = true;
    604         }
    605         psFree(headerItem);
    606     }
    607 
    608     // No header value
    609     return status;
    610 }
    611 
    612 
    613 // Well, not really "write", but check to see if it's there, and matches
    614 bool pmConceptWriteToDefault(pmFPA *fpa, // The FPA that contains the chip
    615                              pmChip *chip, // The chip that contains the cell
    616                              pmCell *cell, // The cell
    617                              psMetadataItem *concept // Concept
    618                             )
    619 {
    620     bool mdOK = true;                   // Status of MD lookup
    621     if (! fpa->camera) {
    622         return false;
    623     }
    624     psMetadata *defaults = psMetadataLookupMD(&mdOK, fpa->camera, "DEFAULTS");
    625     if (! mdOK || ! defaults) {
    626         psError(PS_ERR_IO, false, "Unable to find DEFAULTS in camera configuration.\n");
    627         return false;
    628     }
    629 
    630     psMetadataItem *defItem = psMetadataLookup(defaults, concept->name);
    631     bool status = false;                // Result of checking the database
    632     if (defItem) {
    633         if (defItem->type == PS_DATA_METADATA) {
    634             // A dependent default
    635             psTrace(__func__, 7, "Evaluating dependent default....\n");
    636             psMetadata *dependents = defItem->data.V; // The list of dependents
    637             // Find out what it depends on
    638             psString dependName = psStringCopy(concept->name);
    639             psStringAppend(&dependName, ".DEPEND");
    640             psString dependsOn = psMetadataLookupStr(&mdOK, defaults, dependName);
    641             if (! mdOK) {
    642                 psError(PS_ERR_IO, false, "Unable to find %s in camera configuration for dependent default"
    643                         " --- ignored\n", dependName);
    644                 // XXX: Need to clean up before returning
    645                 return false;
    646             }
    647             psFree(dependName);
    648             // Find the value of the dependent concept
    649             psMetadataItem *depItem = pmConceptReadFromHeader(fpa, chip, cell, dependsOn);
    650             if (! depItem) {
    651                 psError(PS_ERR_IO, true, "Unable to find value for %s (required for %s)\n", dependsOn,
    652                         concept->name);
    653                 return false;
    654             }
    655             if (depItem->type != PS_DATA_STRING) {
    656                 psError(PS_ERR_IO, true, "Value of %s is not of type string, as required for dependency"
    657                         " --- ignored.\n", dependsOn);
    658             }
    659 
    660             defItem = psMetadataLookup(dependents, depItem->data.V); // This is now what we were after
    661         }
    662 
    663         status = compareConcepts(defItem, concept);
    664         if (! status) {
    665             psError(PS_ERR_IO, true, "Concept %s is specified by default in the camera configuration, "
    666                     "but doesn't match the actual value.\n", concept->name);
    667         }
    668     }
    669 
    670     // XXX: Need to clean up before returning
    671     return status;
    672 }
    673 
    674 
    675 // XXX: Not tested at all
    676 // XXX I WOULD NOT TRUST THIS FUNCTION IN THE SLIGHTEST YET! --- PAP
    677 bool pmConceptWriteToDB(pmFPA *fpa, // The FPA that contains the chip
    678                         pmChip *chip, // The chip that contains the cell
    679                         pmCell *cell, // The cell
    680                         psDB *db,    // DB handle
    681                         psMetadataItem *concept // Concept
    682                        )
    683 {
    684     if (! db) {
    685         // No database initialised
    686         return false;
    687     }
    688 
    689     bool mdStatus = true;               // Status of MD lookup
    690     if (! fpa->camera) {
    691         return false;
    692     }
    693     psMetadata *database = psMetadataLookupMD(&mdStatus, fpa->camera, "DATABASE");
    694     if (! mdStatus) {
    695         // No error, because not everyone needs to use the DB
    696         return NULL;
    697     }
    698 
    699     psMetadata *dbLookup = psMetadataLookupMD(&mdStatus, database, concept->name);
    700     if (dbLookup) {
    701         const char *tableName = psMetadataLookupStr(&mdStatus, dbLookup, "TABLE"); // Name of the table
    702         //        const char *colName = psMetadataLookupStr(&mdStatus, dbLookup, "COLUMN"); // Name of the column
    703         const char *givenCols = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENDBCOL"); // Name of "where"
    704         // columns
    705         const char *givenPS = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENPS"); // Values for "where"
    706         // columns
    707 
    708         // Now, need to get the "given"s
    709         if (strlen(givenCols) || strlen(givenPS)) {
    710             psList *cols = psStringSplit(givenCols, ",;", true); // List of column names
    711             psList *values = psStringSplit(givenPS, ",;", true); // List of value names for the columns
    712             psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
    713             if (cols->n != values->n) {
    714                 psLogMsg(__func__, PS_LOG_WARN, "The GIVENDBCOL and GIVENPS entries for %s do not have "
    715                          "the same number of entries --- ignored.\n", concept);
    716             } else {
    717                 // Iterators for the lists
    718                 psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
    719                 psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
    720                 char *column = NULL;    // Name of the column
    721                 while ((column = psListGetAndIncrement(colsIter))) {
    722                     char *name = psListGetAndIncrement(valuesIter); // Name for the value
    723                     if (!strlen(column) || !strlen(name)) {
    724                         psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
    725                                  " empty --- ignored.\n", concept);
    726                     } else {
    727                         // Search for the value name
    728                         psMetadataItem *item = pmConceptReadFromHeader(fpa, chip, cell, name);
    729                         if (! item) {
    730                             item = pmConceptReadFromDefault(fpa, chip, cell, name);
    731                         }
    732                         if (! item) {
    733                             psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB "
    734                                      " lookup on %s --- ignored.\n", name, concept);
    735                         } else {
    736                             // We need to create a new psMetadataItem.  I don't think we can't simply hack
    737                             // the existing one, since that could conceivably cause memory leaks
    738                             psMetadataItem *newItem = psMetadataItemAlloc(concept->name, item->type,
    739                                                       item->comment, item->data.V);
    740                             psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
    741                             psFree(newItem);
    742                         }
    743                     }
    744                     psFree(name);
    745                     psFree(column);
    746                 } // Iterating through the columns
    747                 psFree(colsIter);
    748                 psFree(valuesIter);
    749 
    750                 // Check first to make sure we're only going to touch one row
    751                 psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result
    752                 // Note that we use limit=2 in order to test if there are multiple rows returned
    753                 if (! dbResult || dbResult->n == 0) {
    754                     psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- ignored\n",
    755                              concept->name);
    756                     return false;
    757                 } else {
    758                     if (dbResult->n > 1) {
    759                         psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s --- "
    760                                  " ignored.\n", concept->name);
    761                     }
    762                     // Update the DB
    763                     psMetadata *update = psMetadataAlloc();
    764                     psMetadataAddItem(update, concept, PS_LIST_HEAD, 0);
    765                     psDBUpdateRows(db, tableName, selection, update);
    766                     psFree(update);
    767                     return true;
    768                 }
    769             }
    770             psFree(cols);
    771             psFree(values);
    772         }
    773     } // Doing the "given"s.
    774 
    775     psAbort(__func__, "Shouldn't ever get here?\n");
    776     return false;
    777 }
    778 
    779 
    780 // Concept write from item
    781 bool pmConceptWriteItem(pmFPA *fpa,     // The FPA
    782                         pmChip *chip,   // The chip
    783                         pmCell *cell,   // The cell
    784                         psDB *db,       // DB handle
    785                         psMetadataItem *concept // Concept item
    786                        )
    787 {
    788     if (! fpa->camera) {
    789         return false;
    790     }
    791 
    792     // Try headers, database, defaults in order
    793     psTrace(__func__, 3, "Trying to set concept %s...\n", concept->name);
    794     bool status = pmConceptWriteToCamera(cell, concept); // Status for return
    795     if (! status) {
    796         psTrace(__func__, 5, "Trying header....\n");
    797         status = pmConceptWriteToHeader(fpa, chip, cell, concept);
    798     }
    799     if (! status) {
    800         psTrace(__func__, 5, "Trying database....\n");
    801         status = pmConceptWriteToDB(fpa, chip, cell, db, concept);
    802     }
    803     if (! status) {
    804         psTrace(__func__, 5, "Checking defaults....\n");
    805         status = pmConceptWriteToDefault(fpa, chip, cell, concept);
    806     }
    807 
    808     if (! status) {
    809         psError(PS_ERR_IO, true, "Unable to set %s (%s).\n", concept->name, concept->comment);
    810     }
    811 
    812     return status;
    813 }
    814 
    815 
    816 // Concept write
    817 bool pmConceptWrite(pmFPA *fpa, // The FPA
    818                     pmChip *chip,// The chip
    819                     pmCell *cell,    // The cell
    820                     psDB *db, // DB handle
    821                     psMetadata *concepts, // Concepts MD from which to set
    822                     const char *name // Name of the concept
    823                    )
    824 {
    825     psMetadataItem *concept = psMetadataLookup(concepts, name);
    826     if (! concept) {
    827         psError(PS_ERR_IO, true, "No such concept as %s\n", name);
    828         return false;
    829     }
    830     return pmConceptWriteItem(fpa, chip, cell, db, concept);
    831 }
    832 
    833 #endif
Note: See TracChangeset for help on using the changeset viewer.