json_parser.c 17.1 KB
Newer Older
Tilman Steinweg's avatar
Tilman Steinweg committed
1
/*------------------------------------------------------------------------
2
 * Copyright (C) 2016 For the list of authors, see file AUTHORS.
Tilman Steinweg's avatar
Tilman Steinweg committed
3
4
 *
 * This file is part of SOFI2D.
5
 *
Tilman Steinweg's avatar
Tilman Steinweg committed
6
7
8
 * SOFI2D is free software: you can redistribute it and/or modify
 * 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
 *
Tilman Steinweg's avatar
Tilman Steinweg committed
10
11
12
13
 * SOFI2D is distributed in the hope that it will be useful,
 * 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
16
 * along with SOFI2D. See file COPYING and/or
Tilman Steinweg's avatar
Tilman Steinweg committed
17
18
19
20
21
22
23
24
25
26
27
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
--------------------------------------------------------------------------*/
/* -------------------------------------------------------------
 * function json_parser
 * reads input parameters from input file fomatted according to the json standard
 * also see www.json.org
 *
 *------------------------------------------------------------- */

#include "fd.h"

28
int read_objects_from_intputfile(FILE *fp, char *input_file,char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
29
30
31
32
33
34
35
36
37
38

	char errormessage[STRING_SIZE];
	char varname_tmp1[STRING_SIZE], varname_tmp2[STRING_SIZE], varname_tmp3[STRING_SIZE];
	char varname_tmp4[STRING_SIZE], varname_tmp5[STRING_SIZE];
	char value_tmp1[STRING_SIZE], value_tmp2[STRING_SIZE], value_tmp3[STRING_SIZE];
	char value_tmp4[STRING_SIZE], value_tmp5[STRING_SIZE];
	char cline[STRING_SIZE];
	int occurence_doublequotes = 0, occurence_commas = 0;
	int lineno=0;
	int number_readobject=0;
39
	FILE *fp_in = NULL;
Tilman Steinweg's avatar
Tilman Steinweg committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53

	//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");
		err(errormessage);
	}

	//read line by line into a string covering the whole line
54
	while (fgets(cline,STRING_SIZE,fp_in)) { /* leaves via break */
Tilman Steinweg's avatar
Tilman Steinweg committed
55
56
57
		/* If there are more than 255 characters in one line, this does not work. */
		//count of line numbers
		lineno++;
58

Tilman Steinweg's avatar
Tilman Steinweg committed
59
60
61
62
63
64
65
66
67
		/* tests if line is NOT a comment line*/
		/* tests if line contains at least a colon, double quote and comma sign per line*/
		if (((strstr(cline,":"))&&((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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
			switch (occurence_doublequotes) {
				case 4:

					//up to 5 objects can be defined per line, more can be implemented here
					switch (occurence_commas) {
						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);
								err(errormessage);
							}

							//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);
								err(errormessage);
							}

							//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);
								err(errormessage);
							}

							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);
								err(errormessage);
							}

							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);
								err(errormessage);
							}

							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 1, 3, 5, 7 or 9 commas are allowed per line, but found %i !",lineno,occurence_commas);
							err(errormessage);
							break;
Tilman Steinweg's avatar
Tilman Steinweg committed
199
200
201
202
203
					}

					break;

				default:
204
					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);
Tilman Steinweg's avatar
Tilman Steinweg committed
205
206
207
208
209
210
211
212
213
					err(errormessage);
					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]);

		}
	}
214

Tilman Steinweg's avatar
Tilman Steinweg committed
215
216
217
218
	fclose(fp_in);
	return number_readobject;
}

219
void print_objectlist_screen(FILE *fp, int number_readobject,char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
220
221
222
223
224

	int ii;
	fprintf(fp, "\n===========================================================\n");
	fprintf(fp, "||  Object # | object name \t| object value           ||");
	fprintf(fp, "\n===========================================================\n");
225
226

	for (ii=0; ii<number_readobject; ii++) {
Tilman Steinweg's avatar
Tilman Steinweg committed
227
228
		fprintf(fp, "      %2.0i     | %18s | %s \n",ii+1, varname_list[ii],value_list[ii]);
	}
229

Tilman Steinweg's avatar
Tilman Steinweg committed
230
231
232
	printf("========================================================\n\n");
}

233
int count_occure_charinstring(char stringline[STRING_SIZE], char teststring[]) {
Tilman Steinweg's avatar
Tilman Steinweg committed
234
235
236

	int ii=0, number_occurence=0;

237
	for (ii=0; stringline[ii] != '\0'; ii++) {
Tilman Steinweg's avatar
Tilman Steinweg committed
238
239
240
241
242
243
244
		//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++;
		}
	}
245

Tilman Steinweg's avatar
Tilman Steinweg committed
246
247
248
	return number_occurence;
}

249
void copy_str2str_uptochar(char string_in[STRING_SIZE], char string_out[STRING_SIZE], char teststring[]) {
Tilman Steinweg's avatar
Tilman Steinweg committed
250
251
252

	int ii=0;

253
	for (ii=0; string_in[ii] != '\0'; ii++) {
Tilman Steinweg's avatar
Tilman Steinweg committed
254
255
256
257
		if (strchr(teststring,string_in[ii])) {
			strncpy(string_out,string_in,ii);
		}
	}
258

Tilman Steinweg's avatar
Tilman Steinweg committed
259
260
261
	//return EXIT_SUCCESS;
}

262
263
int get_int_from_objectlist(char string_in[STRING_SIZE], int number_readobject, int *int_buffer,
                            char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
264
265
266
267

	int ii=0, checkifstringfound=1;
	double double_buffer;
	double intpart;
268
	char *string_buffer;
Tilman Steinweg's avatar
Tilman Steinweg committed
269
270
271
	char errormessage[STRING_SIZE];


272
	while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)) {
Tilman Steinweg's avatar
Tilman Steinweg committed
273
274
		ii++;
	}
275

Tilman Steinweg's avatar
Tilman Steinweg committed
276
277
	if (strcmp(varname_list[ii],string_in)==0) {
		//printf("String %s found with value -%s- \n",string_in,value_list[ii]);
278
		if (strlen(value_list[ii])==0) {
Tilman Steinweg's avatar
Tilman Steinweg committed
279
280
281
			sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
			err(errormessage);
		}
282

Tilman Steinweg's avatar
Tilman Steinweg committed
283
284
		memset(&string_buffer, '\0', sizeof(&string_buffer));
		double_buffer = strtod(value_list[ii],&string_buffer);
285

Tilman Steinweg's avatar
Tilman Steinweg committed
286
287
		//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));
288
		if (strlen(string_buffer)>0) {
Tilman Steinweg's avatar
Tilman Steinweg committed
289
290
291
292
293
294
295
296
			/* 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);
			err(errormessage);
		}

		//printf("string %s found with value %f \n",string_in,double_buffer);
		//printf ("%lf = %lf + %lf \n", double_buffer, intpart, fractpart);

297
		if ((modf(double_buffer, &intpart))==0) {
Tilman Steinweg's avatar
Tilman Steinweg committed
298
299
300
			*int_buffer = atoi(value_list[ii]);
			//printf("\nfunc: string %s found with value %i \n",string_in,*int_buffer);
			checkifstringfound=0;
301
302

		} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
303
304
305
306
307
308
309
			//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);
			err(errormessage);
			*int_buffer=-1;
			checkifstringfound=2;
		}

310
	} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
311
312
		checkifstringfound=1;
	}
313

Tilman Steinweg's avatar
Tilman Steinweg committed
314
315
316
	return checkifstringfound;
}

317
318
int get_float_from_objectlist(char string_in[STRING_SIZE], int number_readobject, float *double_buffer,
                              char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
319
320
321

	int ii=0, checkifstringfound=1;
	double double_dummy;
322
	char *string_buffer;
Tilman Steinweg's avatar
Tilman Steinweg committed
323
324
	char errormessage[STRING_SIZE];

325
	while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)) {
Tilman Steinweg's avatar
Tilman Steinweg committed
326
327
		ii++;
	}
328

Tilman Steinweg's avatar
Tilman Steinweg committed
329
330
331
332
	//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]);
333
		if (strlen(value_list[ii])==0) {
Tilman Steinweg's avatar
Tilman Steinweg committed
334
335
336
			sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
			err(errormessage);
		}
337

Tilman Steinweg's avatar
Tilman Steinweg committed
338
339
		memset(&string_buffer, '\0', sizeof(&string_buffer));
		double_dummy = strtod(value_list[ii],&string_buffer);
340

Tilman Steinweg's avatar
Tilman Steinweg committed
341
342
		//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));
343
		if ((strlen(string_buffer)==0) || ((strlen(string_buffer)>0) && ((is_string_blankspace(string_buffer))==1))) {
Tilman Steinweg's avatar
Tilman Steinweg committed
344
345
346
			//printf("\nfunc: string %s found with value %5.5f \n",string_in,double_dummy);
			*double_buffer=double_dummy;
			checkifstringfound=0;
347
348

		} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
349
350
351
352
353
354
			/* 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);
			err(errormessage);
			checkifstringfound=2;
		}

355
	} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
356
357
		checkifstringfound=1;
	}
358

Tilman Steinweg's avatar
Tilman Steinweg committed
359
360
361
362
	return checkifstringfound;
}

int get_string_from_objectlist(char string_in[STRING_SIZE], int number_readobject, char string_buffer[STRING_SIZE],
363
                               char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
364
365
366
367

	int ii=0, checkifstringfound=1;
	char errormessage[STRING_SIZE];

368
	while ((strcmp(varname_list[ii],string_in)!=0) && ((ii+1)<number_readobject)) {
Tilman Steinweg's avatar
Tilman Steinweg committed
369
370
371
		ii++;
		//printf("ii= %i, number_readobject= %i",ii,number_readobject);
	}
372

Tilman Steinweg's avatar
Tilman Steinweg committed
373
374
	if (strcmp(varname_list[ii],string_in)==0) {
		//printf("String %s found with value -%s- \n",string_in,value_list[ii]);
375
		if (strlen(value_list[ii])==0) {
Tilman Steinweg's avatar
Tilman Steinweg committed
376
377
			sprintf(errormessage,"Error in Input file, value of object %s is empty!",string_in);
			err(errormessage);
378
379

		} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
380
381
382
383
384
			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);
		}
385
386

	} else {
Tilman Steinweg's avatar
Tilman Steinweg committed
387
388
389
390
391
392
		checkifstringfound=1;
	}

	return checkifstringfound;
}

393
int is_string_blankspace(char string_in[STRING_SIZE]) {
Tilman Steinweg's avatar
Tilman Steinweg committed
394
395
396
397

	int ii=0, blank_num=0, string_length=0;

	string_length=strlen(string_in);
398
399
400

	while (ii < string_length)  {
		if (string_in[ii++] == ' ')
Tilman Steinweg's avatar
Tilman Steinweg committed
401
402
			blank_num++;
	}
403

Tilman Steinweg's avatar
Tilman Steinweg committed
404
405
	//printf("\nString has length %i and contains %i black spaces \n",string_length, blank_num);
	if (blank_num==string_length) return 1;
406

Tilman Steinweg's avatar
Tilman Steinweg committed
407
408
409
410
	else return 0;

}

411
void remove_blankspaces_around_string(char string_in[STRING_SIZE]) {
Tilman Steinweg's avatar
Tilman Steinweg committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425

	char string_dummy[STRING_SIZE];

	//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);

}

426
427
void add_object_tolist(char string_name[STRING_SIZE],char string_value[STRING_SIZE], int *number_readobject
                       , char **varname_list,char **value_list) {
Tilman Steinweg's avatar
Tilman Steinweg committed
428
429
430
431
432
433
434
435
436

	//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

437
438
	varname_list[*number_readobject] = malloc(STRING_SIZE*sizeof(char *));
	value_list[*number_readobject] = malloc(STRING_SIZE*sizeof(char *));
Tilman Steinweg's avatar
Tilman Steinweg committed
439
440
441
442
443
444
445
446
447
448
449
	//	varname_list[*number_readobject] = (char**)malloc(STRING_SIZE*sizeof(char*));
	//	value_list[*number_readobject] = (char**)malloc(STRING_SIZE*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);
}
450
451
452
453
454