json_parser.c 22 KB
Newer Older
Tilman Steinweg's avatar
Tilman Steinweg committed
1
/*-----------------------------------------------------------------------------------------
Florian Wittkamp's avatar
Florian Wittkamp committed
2
 * Copyright (C) 2016  For the list of authors, see file AUTHORS.
Tilman Steinweg's avatar
Tilman Steinweg committed
3
 *
Florian Wittkamp's avatar
Florian Wittkamp committed
4
 * This file is part of IFOS.
5
 *
Florian Wittkamp's avatar
Florian Wittkamp committed
6
 * IFOS is free software: you can redistribute it and/or modify
Tilman Steinweg's avatar
Tilman Steinweg committed
7 8
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 2.0 of the License only.
9
 *
Florian Wittkamp's avatar
Florian Wittkamp committed
10
 * IFOS is distributed in the hope that it will be useful,
Tilman Steinweg's avatar
Tilman Steinweg committed
11 12 13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14
 *
Tilman Steinweg's avatar
Tilman Steinweg committed
15
 * You should have received a copy of the GNU General Public License
Florian Wittkamp's avatar
Florian Wittkamp committed
16
 * along with IFOS. See file COPYING and/or <http://www.gnu.org/licenses/gpl-2.0.html>.
17
 -----------------------------------------------------------------------------------------*/
Tilman Steinweg's avatar
Tilman Steinweg committed
18 19 20 21 22 23 24 25 26

/*
 * json_parser.c
 *
 */

#include "fd.h"

int read_objects_from_intputfile(FILE *fp, char *input_file,char ** varname_list,char ** value_list) {
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    
    char errormessage[STRING_SIZE2];
    char varname_tmp1[STRING_SIZE2], varname_tmp2[STRING_SIZE2], varname_tmp3[STRING_SIZE2];
    char varname_tmp4[STRING_SIZE2], varname_tmp5[STRING_SIZE2];
    char value_tmp1[STRING_SIZE2], value_tmp2[STRING_SIZE2], value_tmp3[STRING_SIZE2];
    char value_tmp4[STRING_SIZE2], value_tmp5[STRING_SIZE2];
    char cline[STRING_SIZE2];
    int occurence_doublequotes = 0, occurence_commas = 0;
    int lineno=0;
    int number_readobject=0;
    FILE * fp_in = NULL;
    
    //Open parameter input file
    fp_in=fopen(input_file,"r");
    
    
    if (fp_in==NULL) {
        fprintf(fp, "\n==================================================================\n");
        fprintf(fp, "  ERROR: Could not open input file '%s'!", input_file);
        fprintf(fp, "\n==================================================================\n");
        sprintf(errormessage, "\n  in: <read_par_json.c> \n");
Florian Wittkamp's avatar
Florian Wittkamp committed
48
        declare_error(errormessage);
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    }
    
    //read line by line into a string covering the whole line
    while (fgets(cline,STRING_SIZE2,fp_in)){ /* leaves via break */
        /* If there are more than 255 characters in one line, this does not work. */
        //count of line numbers
        lineno++;
        /* tests if line is NOT a comment line*/
        /* tests if line contains at least a colon, double quote sign per line*/
        if (((strstr(cline,":"))&&((strstr(cline,"\"")))) && (!(strstr(cline,"comment")) && !(strstr(cline,"Comment"))))  {
            
            //count number of double quoates and colon signs
            occurence_doublequotes=count_occure_charinstring(cline,"\"");
            occurence_commas=count_occure_charinstring(cline,",");
            
            //only two pais of double quotes are allowed per line
            switch(occurence_doublequotes){
                case 4:
                    //up to 5 objects can be defined per line, more can be implemented here
                    switch(occurence_commas){
                            
                        case 0: //only a single object (name+value) in line
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            //extract object name + object value from the line-string
                            if (sscanf(cline," \"%[^\"]\" : \"%[^\"]\"",varname_tmp1,value_tmp1) != 2) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read object name and object value !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
77
                                declare_error(errormessage);
78 79 80 81 82 83 84 85 86 87 88 89 90 91
                            }
                            
                            //add extracted strings to object list
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            break;
                            
                        case 1: //only a single object (name+value) in line
                            
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            //extract object name + object value from the line-string
                            if (sscanf(cline," \"%[^\"]\" : \"%[^\"]\"",varname_tmp1,value_tmp1) != 2) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read object name and object value !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
92
                                declare_error(errormessage);
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
                            }
                            
                            //add extracted strings to object list
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            break;
                            
                        case 3://two objects (name+value) in line
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            memset(value_tmp2, '\0', sizeof(value_tmp2));
                            memset(varname_tmp2, '\0', sizeof(varname_tmp2));
                            
                            //extract object name + object value from the line-string
                            if (sscanf(cline," \"%[^,],%[^\"]\" : \"%[^,],%[^\"]\"",
                                       varname_tmp1,varname_tmp2,value_tmp1,value_tmp2) != 4) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read two object names and values !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
110
                                declare_error(errormessage);
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
                            }
                            
                            //add extracted strings to object list
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp2, value_tmp2,&number_readobject, varname_list, value_list);
                            
                            break;
                            
                        case 5://three objects (name+value) in line
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(value_tmp2, '\0', sizeof(value_tmp2));
                            memset(value_tmp3, '\0', sizeof(value_tmp3));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            memset(varname_tmp2, '\0', sizeof(varname_tmp2));
                            memset(varname_tmp3, '\0', sizeof(varname_tmp3));
                            
                            if (sscanf(cline," \"%[^,],%[^,],%[^\"]\" : \"%[^,],%[^,],%[^\"]\"",
                                       varname_tmp1,varname_tmp2,varname_tmp3,value_tmp1,value_tmp2,value_tmp3) != 6) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read three object names and values !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
131
                                declare_error(errormessage);
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
                            }
                            
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp2, value_tmp2,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp3, value_tmp3,&number_readobject, varname_list, value_list);
                            
                            break;
                            
                        case 7://four objects (name+value) in line
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(value_tmp2, '\0', sizeof(value_tmp2));
                            memset(value_tmp3, '\0', sizeof(value_tmp3));
                            memset(value_tmp4, '\0', sizeof(value_tmp4));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            memset(varname_tmp2, '\0', sizeof(varname_tmp2));
                            memset(varname_tmp3, '\0', sizeof(varname_tmp3));
                            memset(varname_tmp4, '\0', sizeof(varname_tmp4));
                            
                            if (sscanf(cline," \"%[^,],%[^,],%[^,],%[^\"]\" : \"%[^,],%[^,],%[^,],%[^\"]\"",
                                       varname_tmp1,varname_tmp2,varname_tmp3,varname_tmp4,
                                       value_tmp1,value_tmp2,value_tmp3,value_tmp4) != 8) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read three object names and values !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
155
                                declare_error(errormessage);
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
                            }
                            
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp2, value_tmp2,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp3, value_tmp3,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp4, value_tmp4,&number_readobject, varname_list, value_list);
                            
                            break;
                        case 9://five objects (name+value) in line
                            //remove old data from strings
                            memset(value_tmp1, '\0', sizeof(value_tmp1));
                            memset(value_tmp2, '\0', sizeof(value_tmp2));
                            memset(value_tmp3, '\0', sizeof(value_tmp3));
                            memset(value_tmp4, '\0', sizeof(value_tmp4));
                            memset(value_tmp5, '\0', sizeof(value_tmp5));
                            memset(varname_tmp1, '\0', sizeof(varname_tmp1));
                            memset(varname_tmp2, '\0', sizeof(varname_tmp2));
                            memset(varname_tmp3, '\0', sizeof(varname_tmp3));
                            memset(varname_tmp4, '\0', sizeof(varname_tmp4));
                            memset(varname_tmp5, '\0', sizeof(varname_tmp5));
                            
                            if (sscanf(cline," \"%[^,],%[^,],%[^,],%[^,],%[^\"]\" : \"%[^,],%[^,],%[^,],%[^,],%[^\"]\"",
                                       varname_tmp1,varname_tmp2,varname_tmp3,varname_tmp4,varname_tmp5,
                                       value_tmp1,value_tmp2,value_tmp3,value_tmp4,value_tmp5) != 10) {
                                sprintf(errormessage,"Error in Input file, line %i, cannot read three object names and values !",lineno);
Florian Wittkamp's avatar
Florian Wittkamp committed
181
                                declare_error(errormessage);
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
                            }
                            
                            add_object_tolist(varname_tmp1, value_tmp1,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp2, value_tmp2,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp3, value_tmp3,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp4, value_tmp4,&number_readobject, varname_list, value_list);
                            add_object_tolist(varname_tmp5, value_tmp5,&number_readobject, varname_list, value_list);
                            
                            //very strange: code crashes if both lines are commented here!
                            //this only effects the last case of the switch!
                            //should though not affect anything as long as number_readobject keeps its value
                            //in this case a new object is allocated which is already there...
                            
                            //varname_list = malloc(sizeof(*varname_list));
                            //value_list = malloc(sizeof(*value_list));
                            varname_list[number_readobject] = malloc(STRING_SIZE*sizeof(char*));
                            
                            //varname_list[number_readobject] = (char**)malloc(STRING_SIZE*sizeof(char*));
                            //value_list[number_readobject] = (char**)malloc(STRING_SIZE*sizeof(char*));
                            
                            break;
                        default:
                            sprintf(errormessage,"Error in Input file, line %i, only 0, 1, 3, 5, 7 or 9 commas are allowed per line, but found %i !",lineno,occurence_commas );
Florian Wittkamp's avatar
Florian Wittkamp committed
205
                            declare_error(errormessage);
206 207 208 209 210
                            break;
                    }
                    break;
                default:
                    sprintf(errormessage,"Error in Input file, line %i, only 4 (two pairs) of double quotes are allowed per line, but found %i !",lineno,occurence_doublequotes );
Florian Wittkamp's avatar
Florian Wittkamp committed
211
                    declare_error(errormessage);
212 213 214 215 216 217 218 219 220 221
                    break;
                    
            }
            
            //printf("line %i contains objectno %i varnamme %s with value %s \n",lineno,number_readobject, varname_list[number_readobject-1],value_list[number_readobject-1]);
            
        }
    }
    fclose(fp_in);
    return number_readobject;
Tilman Steinweg's avatar
Tilman Steinweg committed
222 223 224
}

void print_objectlist_screen(FILE *fp, int number_readobject,char ** varname_list,char ** value_list) {
225 226 227 228 229 230 231 232 233 234
    
    int ii;
    fprintf(fp, "\n===========================================================\n");
    fprintf(fp, "||  Object # | object name \t| object value           ||");
    fprintf(fp, "\n===========================================================\n");
    for (ii=0;ii<number_readobject;ii++)
    {
        fprintf(fp, "      %2.0i     | %18s | %s \n",ii+1, varname_list[ii],value_list[ii]);
    }
    printf("========================================================\n\n");
Tilman Steinweg's avatar
Tilman Steinweg committed
235 236 237
}

int count_occure_charinstring(char stringline[STRING_SIZE2], char teststring[]){
238 239 240 241 242 243 244 245 246 247 248 249
    
    int ii=0, number_occurence=0;
    
    for(ii=0; stringline[ii] != '\0'; ii++) {
        //printf("lineno = %i ii= %i cline[ii]= %c  ",lineno, ii,cline[ii]);
        //printf("teststring= %s ",teststring);
        if (strchr(teststring,stringline[ii])) {
            //printf("hello");
            number_occurence++;
        }
    }
    return number_occurence;
Tilman Steinweg's avatar
Tilman Steinweg committed
250 251 252
}

void copy_str2str_uptochar(char string_in[STRING_SIZE2], char string_out[STRING_SIZE2], char teststring[]){
253 254 255 256 257 258 259 260 261
    
    int ii=0;
    
    for(ii=0; string_in[ii] != '\0'; ii++) {
        if (strchr(teststring,string_in[ii])) {
            strncpy(string_out,string_in,ii);
        }
    }
    //return EXIT_SUCCESS;
Tilman Steinweg's avatar
Tilman Steinweg committed
262 263 264
}

int get_int_from_objectlist(char string_in[STRING_SIZE2], int number_readobject, int * int_buffer,
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
                            char ** varname_list,char ** value_list){
    
    int ii=0, checkifstringfound=1;
    double double_buffer;
    double intpart;
    char * string_buffer;
    char errormessage[STRING_SIZE2];
    
    
    while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)){
        ii++;
    }
    if (strcmp(varname_list[ii],string_in)==0) {
        //printf("String %s found with value -%s- \n",string_in,value_list[ii]);
        if (strlen(value_list[ii])==0){
            sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
Florian Wittkamp's avatar
Florian Wittkamp committed
281
            declare_error(errormessage);
282 283 284 285 286 287 288 289
        }
        memset(&string_buffer, '\0', sizeof(*string_buffer));
        double_buffer = strtod(value_list[ii],&string_buffer);
        //printf("From string: -%s- double %f exctracted \n",value_list[ii],double_buffer);
        //printf("RemString found: -%s- with length %i \n",string_buffer,strlen(string_buffer));
        if (strlen(string_buffer)>0){
            /* string empty or 'garbage after double' */
            sprintf(errormessage,"Error in Input file, value of object %s contains more than one float: '%s'!",string_in,string_buffer);
Florian Wittkamp's avatar
Florian Wittkamp committed
290
            declare_error(errormessage);
291 292 293 294 295 296 297 298 299 300 301 302 303
        }
        
        //printf("string %s found with value %f \n",string_in,double_buffer);
        //printf ("%lf = %lf + %lf \n", double_buffer, intpart, fractpart);
        
        if ((modf (double_buffer, &intpart))==0){
            *int_buffer = atoi(value_list[ii]);
            //printf("\nfunc: string %s found with value %i \n",string_in,*int_buffer);
            checkifstringfound=0;
        }
        else {
            //double read, not an int (there are decimal places)
            sprintf(errormessage,"Error in Input file, value of object %s is not an int : %f !",string_in,double_buffer);
Florian Wittkamp's avatar
Florian Wittkamp committed
304
            declare_error(errormessage);
305 306 307 308 309 310 311 312 313
            *int_buffer=-1;
            checkifstringfound=2;
        }
        
    }
    else {
        checkifstringfound=1;
    }
    return checkifstringfound;
Tilman Steinweg's avatar
Tilman Steinweg committed
314 315 316
}

int get_float_from_objectlist(char string_in[STRING_SIZE2], int number_readobject, float * double_buffer,
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
                              char ** varname_list,char ** value_list){
    
    int ii=0, checkifstringfound=1;
    double double_dummy;
    char * string_buffer;
    char errormessage[STRING_SIZE2];
    
    while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)){
        ii++;
    }
    //note: strstr compares if string_in is within varname_list[ii]
    // strcmp compares characterwise if string_in is equal to varname_list[ii]
    if (strcmp(varname_list[ii],string_in)==0) {
        //printf("func1: String %s found with value -%s- \n",string_in,value_list[ii]);
        if (strlen(value_list[ii])==0){
            sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
Florian Wittkamp's avatar
Florian Wittkamp committed
333
            declare_error(errormessage);
334 335 336 337 338 339 340 341 342 343 344 345 346
        }
        memset(&string_buffer, '\0', sizeof(*string_buffer));
        double_dummy = strtod(value_list[ii],&string_buffer);
        //printf("From string: -%s- double %f exctracted \n",value_list[ii],double_dummy);
        //printf("RemString found: -%s- with length %i \n",string_buffer,strlen(string_buffer));
        if ((strlen(string_buffer)==0) || ((strlen(string_buffer)>0) && ((is_string_blankspace(string_buffer))==1))){
            //printf("\nfunc: string %s found with value %5.5f \n",string_in,double_dummy);
            *double_buffer=double_dummy;
            checkifstringfound=0;
        }
        else {
            /* string empty or 'garbage after double' */
            sprintf(errormessage,"Error in Input file, value of object %s contains more than one float: '%s'!",string_in,string_buffer);
Florian Wittkamp's avatar
Florian Wittkamp committed
347
            declare_error(errormessage);
348 349 350 351 352 353 354 355
            checkifstringfound=2;
        }
        
    }
    else {
        checkifstringfound=1;
    }
    return checkifstringfound;
Tilman Steinweg's avatar
Tilman Steinweg committed
356 357 358
}

int get_string_from_objectlist(char string_in[STRING_SIZE2], int number_readobject, char string_buffer[STRING_SIZE2],
359 360 361 362 363 364 365 366 367 368 369 370 371
                               char ** varname_list,char ** value_list){
    
    int ii=0, checkifstringfound=1;
    char errormessage[STRING_SIZE2];
    
    while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)){
        ii++;
        //printf("ii= %i, number_readobject= %i",ii,number_readobject);
    }
    if (strcmp(varname_list[ii],string_in)==0) {
        //printf("String %s found with value -%s- \n",string_in,value_list[ii]);
        if (strlen(value_list[ii])==0){
            sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
Florian Wittkamp's avatar
Florian Wittkamp committed
372
            declare_error(errormessage);
373 374 375 376 377 378 379 380 381 382 383 384 385
        }
        else {
            memset(string_buffer, '\0', sizeof(&string_buffer));
            strcpy(string_buffer,value_list[ii]);
            checkifstringfound=0;
            //printf("\nfunc: string %s found with value -%s- \n",string_in,string_buffer);
        }
    }
    else {
        checkifstringfound=1;
    }
    
    return checkifstringfound;
Tilman Steinweg's avatar
Tilman Steinweg committed
386 387 388
}

int is_string_blankspace(char string_in[STRING_SIZE2]){
389 390 391 392 393 394 395 396 397 398 399 400
    
    int ii=0, blank_num=0, string_length=0;
    
    string_length=strlen(string_in);
    while( ii < string_length)  {
        if(string_in[ii++] == ' ')
            blank_num++;
    }
    //printf("\nString has length %i and contains %i black spaces \n",string_length, blank_num);
    if (blank_num==string_length) return 1;
    else return 0;
    
Tilman Steinweg's avatar
Tilman Steinweg committed
401 402 403
}

void remove_blankspaces_around_string(char string_in[STRING_SIZE2] ) {
404 405 406 407 408 409 410 411 412 413 414 415
    
    char string_dummy[STRING_SIZE2];
    
    //erase dummy string content
    memset(string_dummy, '\0', sizeof(string_dummy));
    //copy string content from input string (ignoring blank spaces before and afer string)
    sscanf(string_in,"%s",string_dummy);
    //erase string content
    memset(string_in, '\0', sizeof(&string_in));
    //copy dummy information withou blank spaces in original string
    strcpy(string_in,string_dummy);
    
Tilman Steinweg's avatar
Tilman Steinweg committed
416 417 418
}

void add_object_tolist(char string_name[STRING_SIZE2],char string_value[STRING_SIZE2], int * number_readobject
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
                       , char ** varname_list,char ** value_list) {
    
    //problem: the sscanf line reads between double quotes, including blank space
    //therefore another sscanf is performed in function remove_blankspace_around_string
    //to remove blank spaces in front and after object name (and value resp.)
    remove_blankspaces_around_string(string_name);
    remove_blankspaces_around_string(string_value);
    
    //allocate memory for a new object
    
    varname_list[*number_readobject] = malloc(STRING_SIZE2*sizeof(char*));
    value_list[*number_readobject] = malloc(STRING_SIZE2*sizeof(char*));
    //	varname_list[*number_readobject] = (char**)malloc(STRING_SIZE2*sizeof(char*));
    //	value_list[*number_readobject] = (char**)malloc(STRING_SIZE2*sizeof(char*));
    
    //copy temp strings into object list
    strcpy(varname_list[*number_readobject],string_name);
    strcpy(value_list[*number_readobject],string_value);
    
    //count number of read objects
    *number_readobject=*number_readobject+1;
    //printf("func after number_readobject : %i \n",number_readobject);
Tilman Steinweg's avatar
Tilman Steinweg committed
441
}