GRASS Programmer's Manual 6.4.1(2011)
reclass.c
Go to the documentation of this file.
00001 #include <string.h>
00002 #include <grass/gis.h>
00003 #include <grass/glocale.h>
00004 
00005 static char *NULL_STRING = "null";
00006 static int reclass_type(FILE *, char **, char **);
00007 static FILE *fopen_cellhd_old(const char *, const char *);
00008 static FILE *fopen_cellhd_new(const char *);
00009 static int get_reclass_table(FILE *, struct Reclass *);
00010 
00011 
00030 int G_is_reclass(const char *name, const char *mapset, char *rname,
00031                  char *rmapset)
00032 {
00033     FILE *fd;
00034     int type;
00035 
00036     fd = fopen_cellhd_old(name, mapset);
00037     if (fd == NULL)
00038         return -1;
00039 
00040     type = reclass_type(fd, &rname, &rmapset);
00041     fclose(fd);
00042     if (type < 0)
00043         return -1;
00044     else
00045         return type != 0;
00046 }
00047 
00048 
00066 int G_is_reclassed_to(const char *name, const char *mapset, int *nrmaps,
00067                       char ***rmaps)
00068 {
00069     FILE *fd;
00070     int i, j, k, l;
00071     char buf2[256], buf3[256];
00072 
00073     fd = G_fopen_old_misc("cell_misc", "reclassed_to", name, mapset);
00074 
00075     if (fd == NULL) {
00076         return -1;
00077     }
00078 
00079     if (rmaps)
00080         *rmaps = NULL;
00081     for (i = 0; !feof(fd) && fgets(buf2, 255, fd);) {
00082         l = strlen(buf2);
00083         for (j = 0, k = 0; j < l; j++) {
00084             if (buf2[j] == '#' ||
00085                 ((buf2[j] == ' ' || buf2[j] == '\t' || buf2[j] == '\n') && k))
00086                 break;
00087             else if (buf2[j] != ' ' && buf2[j] != '\t')
00088                 buf3[k++] = buf2[j];
00089         }
00090 
00091         if (k) {
00092             buf3[k] = 0;
00093             i++;
00094             if (rmaps) {
00095                 *rmaps = (char **)G_realloc(*rmaps, i * sizeof(char *));
00096                 (*rmaps)[i - 1] = (char *)G_malloc(k + 1);
00097                 strncpy((*rmaps)[i - 1], buf3, k);
00098                 (*rmaps)[i - 1][k] = 0;
00099             }
00100         }
00101     }
00102 
00103     if (nrmaps)
00104         *nrmaps = i;
00105 
00106     if (i && rmaps) {
00107         i++;
00108         *rmaps = (char **)G_realloc(*rmaps, i * sizeof(char *));
00109         (*rmaps)[i - 1] = NULL;
00110     }
00111 
00112     fclose(fd);
00113 
00114     return i;
00115 }
00116 
00117 int G_get_reclass(const char *name, const char *mapset,
00118                   struct Reclass *reclass)
00119 {
00120     FILE *fd;
00121     int stat;
00122 
00123     fd = fopen_cellhd_old(name, mapset);
00124     if (fd == NULL)
00125         return -1;
00126     reclass->name = NULL;
00127     reclass->mapset = NULL;
00128     reclass->type = reclass_type(fd, &reclass->name, &reclass->mapset);
00129     if (reclass->type <= 0) {
00130         fclose(fd);
00131         return reclass->type;
00132     }
00133 
00134     switch (reclass->type) {
00135     case RECLASS_TABLE:
00136         stat = get_reclass_table(fd, reclass);
00137         break;
00138     default:
00139         stat = -1;
00140     }
00141 
00142     fclose(fd);
00143     if (stat < 0) {
00144         if (stat == -2)
00145             G_warning(_("Too many reclass categories for [%s in %s]"),
00146                       name, mapset);
00147         else
00148             G_warning(_("Illegal reclass format in header file for [%s in %s]"),
00149                       name, mapset);
00150         stat = -1;
00151     }
00152     return stat;
00153 }
00154 
00155 int G_free_reclass(struct Reclass *reclass)
00156 {
00157     switch (reclass->type) {
00158     case RECLASS_TABLE:
00159         if (reclass->num > 0)
00160             G_free(reclass->table);
00161         reclass->num = 0;
00162         if (reclass->name)
00163             G_free(reclass->name);
00164         if (reclass->mapset)
00165             G_free(reclass->mapset);
00166         reclass->name = NULL;
00167         reclass->mapset = NULL;
00168         break;
00169     default:
00170         break;
00171     }
00172 
00173     return 0;
00174 }
00175 
00176 static int reclass_type(FILE * fd, char **rname, char **rmapset)
00177 {
00178     char buf[128];
00179     char label[128], arg[128];
00180     int i;
00181     int type;
00182 
00183     /* Check to see if this is a reclass file */
00184     if (fgets(buf, sizeof(buf), fd) == NULL)
00185         return 0;
00186     if (strncmp(buf, "reclas", 6))
00187         return 0;
00188     /* later may add other types of reclass */
00189     type = RECLASS_TABLE;
00190 
00191     /* Read the mapset and file name of the REAL cell file */
00192     if (*rname)
00193         **rname = '\0';
00194     if (*rmapset)
00195         **rmapset = '\0';
00196     for (i = 0; i < 2; i++) {
00197         if (fgets(buf, sizeof buf, fd) == NULL)
00198             return -1;
00199         if (sscanf(buf, "%[^:]:%s", label, arg) != 2)
00200             return -1;
00201         if (strncmp(label, "maps", 4) == 0) {
00202             if (*rmapset)
00203                 strcpy(*rmapset, arg);
00204             else
00205                 *rmapset = G_store(arg);
00206         }
00207         else if (strncmp(label, "name", 4) == 0) {
00208             if (*rname)
00209                 strcpy(*rname, arg);
00210             else
00211                 *rname = G_store(arg);
00212         }
00213         else
00214             return -1;
00215     }
00216     if (**rmapset && **rname)
00217         return type;
00218     else
00219         return -1;
00220 }
00221 
00222 static FILE *fopen_cellhd_old(const char *name, const char *mapset)
00223 {
00224     return G_fopen_old("cellhd", name, mapset);
00225 }
00226 
00227 int G_put_reclass(const char *name, const struct Reclass *reclass)
00228 {
00229     FILE *fd;
00230     long min, max;
00231     int found;
00232     char buf1[GPATH_MAX], buf2[GNAME_MAX], *p;
00233     char *xname;
00234 
00235     switch (reclass->type) {
00236     case RECLASS_TABLE:
00237         if (reclass->min > reclass->max || reclass->num <= 0) {
00238             G_fatal_error(_("Illegal reclass request"));
00239             return -1;
00240         }
00241         break;
00242     default:
00243         G_fatal_error(_("Illegal reclass type"));
00244         return -1;
00245     }
00246 
00247     fd = fopen_cellhd_new(name);
00248     if (fd == NULL) {
00249         G_warning(_("Unable to create header file for [%s in %s]"),
00250                   name, G_mapset());
00251         return -1;
00252     }
00253 
00254     fprintf(fd, "reclass\n");
00255     fprintf(fd, "name: %s\n", reclass->name);
00256     fprintf(fd, "mapset: %s\n", reclass->mapset);
00257 
00258     /* find first non-null entry */
00259     for (min = 0; min < reclass->num; min++)
00260         if (!G_is_c_null_value(&reclass->table[min]))
00261             break;
00262     /* find last non-zero entry */
00263     for (max = reclass->num - 1; max >= 0; max--)
00264         if (!G_is_c_null_value(&reclass->table[max]))
00265             break;
00266 
00267     /*
00268      * if the resultant table is empty, write out a dummy table
00269      * else write out the table
00270      *   first entry is #min
00271      *   rest are translations for cat min+i
00272      */
00273     if (min > max)
00274         fprintf(fd, "0\n");
00275     else {
00276         fprintf(fd, "#%ld\n", (long)reclass->min + min);
00277         while (min <= max) {
00278             if (G_is_c_null_value(&reclass->table[min]))
00279                 fprintf(fd, "%s\n", NULL_STRING);
00280             else
00281                 fprintf(fd, "%ld\n", (long)reclass->table[min]);
00282             min++;
00283         }
00284     }
00285     fclose(fd);
00286 
00287     strcpy(buf2, reclass->name);
00288     if ((p = strchr(buf2, '@')))
00289         *p = 0;
00290 
00291     G__file_name_misc(buf1, "cell_misc", "reclassed_to", reclass->name,
00292                       reclass->mapset);
00293 
00294     fd = fopen(buf1, "a+");
00295     if (fd == NULL) {
00296 #if 0
00297         G_warning(_("Unable to create dependency file in [%s in %s]"),
00298                   buf2, reclass->mapset);
00299 #endif
00300         return 1;
00301     }
00302 
00303     fseek(fd, 0L, SEEK_SET);
00304 
00305     xname = G_fully_qualified_name(name, G_mapset());
00306     found = 0;
00307     for (;;) {
00308         char buf[GNAME_MAX + GMAPSET_MAX];
00309         if (!G_getl2(buf, sizeof(buf), fd))
00310             break;
00311         if (strcmp(xname, buf) == 0) {
00312             found = 1;
00313             break;
00314         }
00315     }
00316 
00317     if (!found)
00318         fprintf(fd, "%s\n", xname);
00319 
00320     G_free(xname);
00321     fclose(fd);
00322 
00323     return 1;
00324 }
00325 
00326 static FILE *fopen_cellhd_new(const char *name)
00327 {
00328     return G_fopen_new("cellhd", name);
00329 }
00330 
00331 static int get_reclass_table(FILE * fd, struct Reclass *reclass)
00332 {
00333     char buf[128];
00334     int n;
00335     int first, null_str_size;
00336     CELL cat;
00337     long len;
00338 
00339     /*
00340      * allocate the table, expanding as each entry is read
00341      * note that G_realloc() will become G_malloc() if ptr in
00342      * NULL
00343      */
00344     reclass->min = 0;
00345     reclass->table = NULL;
00346     null_str_size = strlen(NULL_STRING);
00347     n = 0;
00348     first = 1;
00349     while (fgets(buf, sizeof buf, fd)) {
00350         if (first) {
00351             first = 0;
00352             if (sscanf(buf, "#%d", &cat) == 1) {
00353                 reclass->min = cat;
00354                 continue;
00355             }
00356         }
00357         if (strncmp(buf, NULL_STRING, null_str_size) == 0)
00358             G_set_c_null_value(&cat, 1);
00359         else {
00360             if (sscanf(buf, "%d", &cat) != 1)
00361                 return -1;
00362         }
00363         n++;
00364         len = (long)n *sizeof(CELL);
00365 
00366         if (len != (int)len) {  /* check for int overflow */
00367             if (reclass->table != NULL)
00368                 G_free(reclass->table);
00369             return -2;
00370         }
00371         reclass->table = (CELL *) G_realloc((char *)reclass->table, (int)len);
00372         reclass->table[n - 1] = cat;
00373     }
00374     reclass->max = reclass->min + n - 1;
00375     reclass->num = n;
00376     return 1;
00377 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines