GRASS Programmer's Manual
6.4.1(2011)
|
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 }