src/cffiles.c

Go to the documentation of this file.
00001 
00011 #include <config.h>
00012 #include <libcf_src.h>
00013 #include <libcf_int.h>
00014 #include <netcdf.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <stdio.h>
00018 #include <time.h>
00165 int
00166 nccf_inq_libvers(char *version_string)
00167 {
00168    char ver[NC_MAX_NAME + 1];
00169 
00170    sprintf(ver, "libcf library version %s", VERSION);
00171    if (version_string)
00172       strcpy(version_string, ver);
00173 
00174    return CF_NOERR;
00175 }
00176 
00177 /* Append string to a named global attribute. Create the attribute if
00178  * it doesn't exist. */
00179 static int
00180 nccf_append_att(int ncid, const char *name, const char *string)
00181 {
00182    char *att_str = NULL;
00183    size_t len, new_len;
00184    int ret;
00185 
00186    /* Find out if there is an attribute of this name. */
00187    ret = nc_inq_attlen(ncid, NC_GLOBAL, name, &len);
00188 
00189    if (ret == NC_ENOTATT)
00190    {
00191       /* Create the attribute. I will null-terminate this
00192        * attribute. */
00193       if ((ret = nc_put_att_text(ncid, NC_GLOBAL, name, 
00194                                  strlen(string) + 1, string)))
00195          return ret;
00196    }
00197    else if (ret == NC_NOERR)
00198    {
00199       /* The attribute already exists. Get memory to hold the existing
00200        * att plus our version string. Add one for the space, and one
00201        * for a terminating null. */
00202       new_len = len + strlen(string) + 1;
00203       if (!(att_str = malloc(new_len + 1)))
00204          return CF_ENOMEM;
00205 
00206       /* Get the existing attribute value. */
00207       if ((ret = nc_get_att_text(ncid, NC_GLOBAL, name, att_str)))
00208          BAIL(CF_ENETCDF);
00209 
00210       /* If it's already in the string, our work is done.*/
00211       if (strstr(att_str, string))
00212       {
00213          free(att_str);
00214          return CF_NOERR;
00215       }
00216 
00217       /* Append our string to the existing att. */
00218       att_str[len] = 0;
00219       strcat(att_str, " ");
00220       strcat(att_str, string);
00221 
00222       /* Delete the existing attribute, so we can rewrite it. */
00223       if ((ret = nc_del_att(ncid, NC_GLOBAL, name)))
00224          BAIL(ret);
00225 
00226       /* Rewrite the attribute with our string appended. */
00227       if ((ret = nc_put_att_text(ncid, NC_GLOBAL, name, 
00228                                  strlen(att_str) + 1, att_str)))
00229          BAIL(ret);
00230    }
00231 
00232   exit:
00233    if (att_str) 
00234       free(att_str);
00235    return ret;
00236 }
00237 
00253 int 
00254 nccf_def_convention(int ncid)
00255 {
00256    return nccf_append_att(ncid, CF_CONVENTIONS, CF_CONVENTION_STRING);
00257 }
00258 
00275 int 
00276 nccf_inq_convention(int ncid, int *cf_convention)
00277 {
00278    size_t len, new_len;
00279    char *existing_att = NULL;
00280    int ret = CF_NOERR;
00281 
00282    /* Find out if there is a conventions attribute. */
00283    ret = nc_inq_attlen(ncid, NC_GLOBAL, CF_CONVENTIONS, &len);
00284 
00285    if (ret == NC_NOERR)
00286    {
00287       /* Get memory to hold the existing att plus our version
00288        * string. */
00289       new_len = len + strlen(CF_CONVENTION_STRING) + 1;
00290       if (!(existing_att = malloc(new_len)))
00291          return CF_ENOMEM;
00292 
00293       /* Get the existing att. */
00294       if ((ret = nc_get_att_text(ncid, NC_GLOBAL, CF_CONVENTIONS, 
00295                                  existing_att)))
00296          BAIL(CF_ENETCDF);
00297 
00298       /* If it's already in the string, our work is done.*/
00299       if (strstr(existing_att, CF_CONVENTION_STRING))
00300       {
00301          if (cf_convention)
00302             *cf_convention = 1;
00303          ret = CF_NOERR;
00304       }
00305    }
00306    else if (ret == NC_ENOTATT)
00307    {
00308       /* No conventions att means no cf conventions. ;-( But this is
00309        * not an error. */
00310       if (cf_convention)
00311          *cf_convention = 0;
00312       ret = NC_NOERR;
00313    }
00314    else
00315       BAIL(CF_ENETCDF);
00316 
00317   exit:
00318    if (existing_att) 
00319       free(existing_att);
00320    return ret;
00321 }
00322 
00323 
00350 /* Add CF_recomended attributes to a file. Any NULLs will cause the
00351  * cooresponding attribute to not be written. */
00352 int
00353 nccf_def_file(int ncid, const char *title, const char *history)
00354 {
00355    int ret;
00356 
00357    /* Make sure the file is labled with "CF-1.0" in a Conventions
00358     * attribute. */
00359    if ((ret = nccf_def_convention(ncid)))
00360       return ret;
00361 
00362    /* If title already exists this will return an error. */
00363    if (title)
00364       if ((ret = nc_put_att_text(ncid, NC_GLOBAL, CF_TITLE,
00365                                     strlen(title) + 1, title)))
00366          return ret;
00367 
00368    /* This will append to the history attribute, creating it if
00369     * needed. */
00370    if (history)
00371       ret = nccf_add_history(ncid, history);
00372 
00373    return ret;
00374 }
00375 
00377 #define NCCF_MAX_TIMESTAMP_LEN 35
00378 
00390 int 
00391 nccf_add_history(int ncid, const char *history)
00392 {
00393    time_t now;
00394    char *hist_str;
00395    char timestamp[NCCF_MAX_TIMESTAMP_LEN + 1];
00396    struct tm *timptr;
00397    int ret;
00398 
00399    if (!history)
00400       return NC_NOERR;
00401 
00402    /* Get the date and time. */
00403    time(&now);
00404    if (!(timptr = localtime(&now)))
00405       return CF_ETIME;
00406    if (!strftime(timestamp, NCCF_MAX_TIMESTAMP_LEN, "%x %X", timptr))
00407       return CF_ETIME;
00408 
00409    /* Allocate space for this string, with the time prepended. */
00410    if (!(hist_str = malloc(strlen(history) + strlen(timestamp) + 2)))
00411       return CF_ENOMEM;
00412 
00413    /* Create a string with the time and then the user's history
00414     * comment. */
00415    sprintf(hist_str, "%s %s\n", timestamp, history);
00416    
00417    /* Now append that to the existing history att, or create one. */
00418    ret = nccf_append_att(ncid, CF_HISTORY, hist_str);
00419 
00420    /* Free our memory. */
00421    free(hist_str);
00422 
00423    return ret;
00424 }
00425 
00459 int
00460 nccf_inq_file(int ncid, size_t *title_lenp, char *title, 
00461               size_t *history_lenp, char *history)
00462 {
00463    int ret;
00464 
00465    /* Find length of title. */
00466    if (title_lenp)
00467       if ((ret = nc_inq_attlen(ncid, NC_GLOBAL, CF_TITLE, title_lenp)))
00468          return ret;
00469 
00470    /* Get title. */
00471    if (title)
00472       if ((ret = nc_get_att_text(ncid, NC_GLOBAL, CF_TITLE, title)))
00473          return ret;
00474 
00475    /* Find length of history. */
00476    if (history_lenp)
00477       if ((ret = nc_inq_attlen(ncid, NC_GLOBAL, CF_HISTORY, history_lenp)))
00478          return ret;
00479 
00480    /* Get history. */
00481    if (history)
00482       if ((ret = nc_get_att_text(ncid, NC_GLOBAL, CF_HISTORY, history)))
00483          return ret;
00484 
00485    return NC_NOERR;
00486 
00487 }
00488 
00519 int 
00520 nccf_def_notes(int ncid, int varid, const char *institution, 
00521                const char *source, const char *comment, 
00522                const char *references)
00523 {
00524    int ret;
00525 
00526    if (institution)
00527       if ((ret = nc_put_att_text(ncid, varid, CF_INSTITUTION,
00528                                     strlen(institution) + 1, institution)))
00529          return ret;
00530 
00531    if (source)
00532       if ((ret = nc_put_att_text(ncid, varid, CF_SOURCE,
00533                                     strlen(source) + 1, source)))
00534          return ret;
00535 
00536    if (comment)
00537       if ((ret = nc_put_att_text(ncid, varid, CF_COMMENT,
00538                                     strlen(comment) + 1, comment)))
00539          return ret;
00540 
00541    if (references)
00542       if ((ret = nc_put_att_text(ncid, varid, CF_REFERENCES,
00543                                     strlen(references) + 1, references)))
00544          return ret;
00545 
00546    return CF_NOERR;
00547 }
00548 
00595 int nccf_inq_notes(int ncid, int varid, size_t *institution_lenp, 
00596                    char *institution, size_t *source_lenp, char *source, 
00597                    size_t *comment_lenp, char *comment, 
00598                    size_t *references_lenp, char *references)
00599 {
00600    int ret;
00601 
00602    if (institution_lenp)
00603    {
00604       ret = nc_inq_attlen(ncid, varid, CF_INSTITUTION, institution_lenp);
00605       if (ret == NC_ENOTATT)
00606          *institution_lenp = 0;
00607       else if (ret)
00608          return ret;
00609    }
00610 
00611    if (institution)
00612    {
00613       ret = nc_get_att_text(ncid, varid, CF_INSTITUTION, institution);
00614       if (ret == NC_ENOTATT)
00615          strcpy(institution, "");
00616       else if (ret)
00617          return ret;
00618    }
00619 
00620    if (source_lenp)
00621    {
00622       ret = nc_inq_attlen(ncid, varid, CF_SOURCE, source_lenp);
00623       if (ret == NC_ENOTATT)
00624          *source_lenp = 0;
00625       else if (ret)
00626          return ret;
00627    }
00628 
00629    if (source)
00630    {
00631       ret = nc_get_att_text(ncid, varid, CF_SOURCE, source);
00632       if (ret == NC_ENOTATT)
00633          strcpy(source, "");
00634       else if (ret)
00635          return ret;
00636    }
00637 
00638    if (comment_lenp)
00639    {
00640       ret = nc_inq_attlen(ncid, varid, CF_COMMENT, comment_lenp);
00641       if (ret == NC_ENOTATT)
00642          *comment_lenp = 0;
00643       else if (ret)
00644          return ret;
00645    }
00646 
00647    if (comment)
00648    {
00649       ret = nc_get_att_text(ncid, varid, CF_COMMENT, comment);
00650       if (ret == NC_ENOTATT)
00651          strcpy(comment, "");
00652       else if (ret)
00653          return ret;
00654    }
00655 
00656    if (references_lenp)
00657    {
00658       ret = nc_inq_attlen(ncid, varid, CF_REFERENCES, references_lenp);
00659       if (ret == NC_ENOTATT)
00660          *references_lenp = 0;
00661       else if (ret)
00662          return ret;
00663    }
00664 
00665    if (references)
00666    {
00667       ret = nc_get_att_text(ncid, varid, CF_REFERENCES, references);
00668       if (ret == NC_ENOTATT)
00669          strcpy(references, "");
00670       else if (ret)
00671          return ret;
00672    }
00673    
00674    return NC_NOERR;
00675 }
 All Classes Files Functions Defines

Generated on Tue Mar 1 2011 06:36:59 for libCF. LibCF is a Unidata library.