Store CPU list in a metadata.json file
This allows early access to the CPU list in order to emit the PRV header before consuming events from the streams.
This commit is contained in:
		
							parent
							
								
									763bcf7c33
								
							
						
					
					
						commit
						60862db890
					
				
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							| @ -17,16 +17,16 @@ all: $(BIN) | ||||
| libovni.a: ovni.o | ||||
| 	ar -crs $@ $^ | ||||
| 
 | ||||
| dump: ovni.o dump.o | ||||
| dump: ovni.o dump.o parson.o | ||||
| 
 | ||||
| test_speed: test_speed.c ovni.o | ||||
| test_speed: test_speed.c ovni.o parson.o | ||||
| 
 | ||||
| emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o | ||||
| emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o parson.o | ||||
| 
 | ||||
| libovni.so: ovni.o | ||||
| libovni.so: ovni.o parson.o | ||||
| 	$(LINK.c) -shared $^ -o $@ | ||||
| 
 | ||||
| ovni2prv: ovni2prv.c ovni.o | ||||
| ovni2prv: ovni2prv.c ovni.o parson.o | ||||
| 
 | ||||
| ovnisync: ovnisync.c | ||||
| 	mpicc -lm $^ -o $@ | ||||
|  | ||||
							
								
								
									
										120
									
								
								emu.c
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								emu.c
									
									
									
									
									
								
							| @ -190,6 +190,7 @@ emulate(struct ovni_emu *emu) | ||||
| 		ovni_load_next_event(stream); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	emu->lastclock = 0; | ||||
| 
 | ||||
| 	/* Then process all events */ | ||||
| @ -237,6 +238,112 @@ emu_get_thread(struct ovni_emu *emu, int tid) | ||||
| 	return thread; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid) | ||||
| { | ||||
| 	/* The logical id must match our index */ | ||||
| 	assert(i == loom->ncpus); | ||||
| 
 | ||||
| 	assert(loom->cpu[i].state == CPU_ST_UNKNOWN); | ||||
| 
 | ||||
| 	loom->cpu[loom->ncpus].state = CPU_ST_READY; | ||||
| 	loom->cpu[loom->ncpus].i = i; | ||||
| 	loom->cpu[loom->ncpus].phyid = phyid; | ||||
| 	loom->cpu[loom->ncpus].gindex = emu->total_cpus++; | ||||
| 
 | ||||
| 	dbg("new cpu %d at phyid=%d\n", i, phyid); | ||||
| 
 | ||||
| 	loom->ncpus++; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, struct ovni_eproc *proc) | ||||
| { | ||||
| 	JSON_Array *cpuarray; | ||||
| 	JSON_Object *cpu; | ||||
| 	JSON_Object *meta; | ||||
| 	int i, index, phyid; | ||||
| 
 | ||||
| 	meta = json_value_get_object(proc->meta); | ||||
| 
 | ||||
| 	assert(meta); | ||||
| 
 | ||||
| 	cpuarray = json_object_get_array(meta, "cpus"); | ||||
| 
 | ||||
| 	/* This process doesn't have the cpu list */ | ||||
| 	if(cpuarray == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	assert(loom->ncpus == 0); | ||||
| 
 | ||||
| 	for(i = 0; i < json_array_get_count(cpuarray); i++) | ||||
| 	{ | ||||
| 		cpu = json_array_get_object(cpuarray, i); | ||||
| 
 | ||||
| 		index = (int) json_object_get_number(cpu, "index"); | ||||
| 		phyid = (int) json_object_get_number(cpu, "phyid"); | ||||
| 
 | ||||
| 		add_new_cpu(emu, loom, index, phyid); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Obtain CPUs in the metadata files and other data */ | ||||
| static int | ||||
| load_metadata(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, j, k, s; | ||||
| 	struct ovni_loom *loom; | ||||
| 	struct ovni_eproc *proc; | ||||
| 	struct ovni_ethread *thread; | ||||
| 	struct ovni_stream *stream; | ||||
| 	struct ovni_trace *trace; | ||||
| 
 | ||||
| 	trace = &emu->trace; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 
 | ||||
| 			proc_load_cpus(emu, loom, proc); | ||||
| 		} | ||||
| 
 | ||||
| 		/* One of the process must have the list of CPUs */ | ||||
| 		/* FIXME: The CPU list should be at the loom dir */ | ||||
| 		assert(loom->ncpus > 0); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| destroy_metadata(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, j, k, s; | ||||
| 	struct ovni_loom *loom; | ||||
| 	struct ovni_eproc *proc; | ||||
| 	struct ovni_ethread *thread; | ||||
| 	struct ovni_stream *stream; | ||||
| 	struct ovni_trace *trace; | ||||
| 
 | ||||
| 	trace = &emu->trace; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 
 | ||||
| 			assert(proc->meta); | ||||
| 			json_value_free(proc->meta); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| @ -256,16 +363,23 @@ main(int argc, char *argv[]) | ||||
| 	memset(&emu, 0, sizeof(emu)); | ||||
| 
 | ||||
| 	if(ovni_load_trace(&emu.trace, tracedir)) | ||||
| 		return 1; | ||||
| 		abort(); | ||||
| 
 | ||||
| 	if(ovni_load_streams(&emu.trace)) | ||||
| 		return 1; | ||||
| 		abort(); | ||||
| 
 | ||||
| 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", 10); | ||||
| 	if(load_metadata(&emu) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 
 | ||||
| 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", emu.total_cpus); | ||||
| 
 | ||||
| 	emulate(&emu); | ||||
| 
 | ||||
| 	destroy_metadata(&emu); | ||||
| 
 | ||||
| 	ovni_free_streams(&emu.trace); | ||||
| 
 | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										5
									
								
								emu.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								emu.h
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ | ||||
| 
 | ||||
| #include "ovni.h" | ||||
| #include "uthash.h" | ||||
| #include "parson.h" | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| /* Debug macros */ | ||||
| @ -91,6 +92,8 @@ struct ovni_eproc { | ||||
| 	size_t nthreads; | ||||
| 	struct ovni_ethread thread[OVNI_MAX_THR]; | ||||
| 
 | ||||
| 	JSON_Value *meta; | ||||
| 
 | ||||
| 	/* ------ Subsystem specific data --------*/ | ||||
| 	/* TODO: Use dynamic allocation */ | ||||
| 
 | ||||
| @ -189,7 +192,7 @@ struct ovni_emu { | ||||
| 	/* Total counters */ | ||||
| 	int total_thread; | ||||
| 	int total_proc; | ||||
| 	int total_cpu; | ||||
| 	int total_cpus; | ||||
| }; | ||||
| 
 | ||||
| /* Emulator function declaration */ | ||||
|  | ||||
							
								
								
									
										70
									
								
								emu_ovni.c
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								emu_ovni.c
									
									
									
									
									
								
							| @ -243,74 +243,6 @@ ev_affinity(struct ovni_emu *emu) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| ev_cpu_count(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, max_ncpus, max_phyid; | ||||
| 	struct ovni_loom *loom; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 	max_ncpus = emu->cur_ev->payload.i32[0]; | ||||
| 	max_phyid = emu->cur_ev->payload.i32[1]; | ||||
| 
 | ||||
| 	assert(max_ncpus < OVNI_MAX_CPU); | ||||
| 	assert(max_phyid < OVNI_MAX_CPU); | ||||
| 
 | ||||
| 	for(i=0; i<OVNI_MAX_CPU; i++) | ||||
| 	{ | ||||
| 		loom->cpu[i].state = CPU_ST_UNKNOWN; | ||||
| 		loom->cpu[i].i = -1; | ||||
| 		loom->cpu[i].phyid = -1; | ||||
| 		loom->cpu[i].gindex = -1; | ||||
| 	} | ||||
| 
 | ||||
| 	loom->ncpus = 0; | ||||
| 	loom->max_ncpus = max_ncpus; | ||||
| 	loom->max_phyid = max_phyid; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| ev_cpu_id(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, phyid; | ||||
| 	struct ovni_loom *loom; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 	i = emu->cur_ev->payload.i32[0]; | ||||
| 	phyid = emu->cur_ev->payload.i32[1]; | ||||
| 
 | ||||
| 	/* The logical id must match our index */ | ||||
| 	assert(i == loom->ncpus); | ||||
| 
 | ||||
| 	assert(0 <= phyid && phyid <= loom->max_phyid); | ||||
| 
 | ||||
| 	assert(loom->cpu[i].state == CPU_ST_UNKNOWN); | ||||
| 
 | ||||
| 	loom->cpu[loom->ncpus].state = CPU_ST_READY; | ||||
| 	loom->cpu[loom->ncpus].i = i; | ||||
| 	loom->cpu[loom->ncpus].phyid = phyid; | ||||
| 	loom->cpu[loom->ncpus].gindex = emu->total_cpu++; | ||||
| 
 | ||||
| 	dbg("new cpu %d at phyid=%d\n", i, phyid); | ||||
| 
 | ||||
| 	loom->ncpus++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| ev_cpu(struct ovni_emu *emu) | ||||
| { | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case 'n': ev_cpu_count(emu); break; | ||||
| 		case 'i': ev_cpu_id(emu); break; | ||||
| 		default: | ||||
| 			dbg("unknown cpu event value %c\n", | ||||
| 					emu->cur_ev->header.value); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_pre_ovni(struct ovni_emu *emu) | ||||
| { | ||||
| @ -320,7 +252,6 @@ hook_pre_ovni(struct ovni_emu *emu) | ||||
| 	{ | ||||
| 		case 'H': ev_thread(emu); break; | ||||
| 		case 'A': ev_affinity(emu); break; | ||||
| 		case 'C': ev_cpu(emu); break; | ||||
| 		case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break; | ||||
| 		default: | ||||
| 			dbg("unknown ovni event class %c\n", | ||||
| @ -410,7 +341,6 @@ hook_emit_ovni(struct ovni_emu *emu) | ||||
| 			emit_thread_state(emu); | ||||
| 			/* falltrough */ | ||||
| 		case 'A': | ||||
| 		case 'C': | ||||
| 			emit_thread_count(emu); | ||||
| 			//emit_current_pid(emu);
 | ||||
| 			break; | ||||
|  | ||||
							
								
								
									
										130
									
								
								ovni.c
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								ovni.c
									
									
									
									
									
								
							| @ -19,6 +19,7 @@ | ||||
| 
 | ||||
| #include "ovni.h" | ||||
| #include "ovni_trace.h" | ||||
| #include "parson.h" | ||||
| 
 | ||||
| #define ENABLE_DEBUG | ||||
| 
 | ||||
| @ -93,8 +94,113 @@ create_trace_stream() | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| proc_metadata_init(struct ovni_rproc *proc) | ||||
| { | ||||
| 	JSON_Value *meta; | ||||
| 
 | ||||
| 	proc->meta = json_value_init_object(); | ||||
| 
 | ||||
| 	if(proc->meta == NULL) | ||||
| 	{ | ||||
| 		err("failed to create json object\n"); | ||||
| 		abort(); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| proc_metadata_store(struct ovni_rproc *proc) | ||||
| { | ||||
| 	char path[PATH_MAX]; | ||||
|         | ||||
| 	snprintf(path, PATH_MAX, "%s/metadata.json", proc->dir); | ||||
| 
 | ||||
| 	assert(proc->meta != NULL); | ||||
| 
 | ||||
| 	puts(json_serialize_to_string_pretty(proc->meta)); | ||||
| 
 | ||||
| 	if(json_serialize_to_file_pretty(proc->meta, path) != JSONSuccess) | ||||
| 	{ | ||||
| 		err("failed to write proc metadata\n"); | ||||
| 		abort(); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_add_cpu(int index, int phyid) | ||||
| { | ||||
| 	JSON_Array *cpuarray; | ||||
| 	JSON_Object *cpu; | ||||
| 	JSON_Object *meta; | ||||
| 	JSON_Value *valcpu, *valcpuarray; | ||||
| 	int append = 0; | ||||
| 
 | ||||
| 	assert(rproc.ready == 1); | ||||
| 	assert(rproc.meta != NULL); | ||||
| 
 | ||||
| 	meta = json_value_get_object(rproc.meta); | ||||
| 
 | ||||
| 	assert(meta); | ||||
| 
 | ||||
| 	/* Find the CPU array and create it if needed  */ | ||||
| 	cpuarray = json_object_dotget_array(meta, "cpus"); | ||||
| 
 | ||||
| 	if(cpuarray == NULL) | ||||
| 	{ | ||||
| 		valcpuarray = json_value_init_array(); | ||||
| 		assert(valcpuarray); | ||||
| 
 | ||||
| 		cpuarray = json_array(valcpuarray); | ||||
| 		assert(cpuarray); | ||||
| 		append = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	valcpuarray = json_array_get_wrapping_value(cpuarray); | ||||
| 	assert(valcpuarray); | ||||
| 
 | ||||
| 	valcpu = json_value_init_object(); | ||||
| 	assert(valcpu); | ||||
| 
 | ||||
| 	cpu = json_object(valcpu); | ||||
| 	assert(cpu); | ||||
| 
 | ||||
| 	if(json_object_set_number(cpu, "index", index) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	if(json_object_set_number(cpu, "phyid", phyid) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	if(json_array_append_value(cpuarray, valcpu) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	if(append && json_object_set_value(meta, "cpus", valcpuarray) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	//puts(json_serialize_to_string_pretty(rproc.meta));
 | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| proc_set_app(int appid) | ||||
| { | ||||
| 	JSON_Object *meta; | ||||
| 
 | ||||
| 	assert(rproc.ready == 1); | ||||
| 	assert(rproc.meta != NULL); | ||||
| 
 | ||||
| 	meta = json_value_get_object(rproc.meta); | ||||
| 
 | ||||
| 	assert(meta); | ||||
| 
 | ||||
| 	if(json_object_set_number(meta, "app_id", appid) != 0) | ||||
| 		abort(); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_proc_init(char *loom, int proc) | ||||
| ovni_proc_init(int app, char *loom, int proc) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| @ -105,6 +211,7 @@ ovni_proc_init(char *loom, int proc) | ||||
| 	/* FIXME: strcpy is insecure */ | ||||
| 	strcpy(rproc.loom, loom); | ||||
| 	rproc.proc = proc; | ||||
| 	rproc.app = app; | ||||
| 
 | ||||
| 	/* By default we use the monotonic clock */ | ||||
| 	rproc.clockid = CLOCK_MONOTONIC; | ||||
| @ -112,8 +219,22 @@ ovni_proc_init(char *loom, int proc) | ||||
| 	if(create_trace_dirs(OVNI_TRACEDIR, loom, proc)) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	if(proc_metadata_init(&rproc) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	rproc.ready = 1; | ||||
| 
 | ||||
| 	proc_set_app(app); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_proc_fini() | ||||
| { | ||||
| 	if(proc_metadata_store(&rproc) != 0) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -511,6 +632,11 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir) | ||||
| 	proc->index = index; | ||||
| 	proc->gindex = total_procs++; | ||||
| 
 | ||||
| 	sprintf(path, "%s/%s", procdir, "metadata.json"); | ||||
| 	proc->meta = json_parse_file_with_comments(path); | ||||
| 
 | ||||
| 	assert(proc->meta); | ||||
| 
 | ||||
| 	if((dir = opendir(procdir)) == NULL) | ||||
| 	{ | ||||
| 		fprintf(stderr, "opendir %s failed: %s\n", | ||||
| @ -545,6 +671,8 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir) | ||||
| 
 | ||||
| 	closedir(dir); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										11
									
								
								ovni.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ovni.h
									
									
									
									
									
								
							| @ -8,6 +8,8 @@ | ||||
| #include <linux/limits.h> | ||||
| #include <limits.h> | ||||
| 
 | ||||
| #include "parson.h" | ||||
| 
 | ||||
| #define OVNI_MAX_CPU 256 | ||||
| #define OVNI_MAX_PROC 32 | ||||
| #define OVNI_MAX_THR 32 | ||||
| @ -93,6 +95,7 @@ struct ovni_rproc { | ||||
| 	/* Path of the process tracedir */ | ||||
| 	char dir[PATH_MAX]; | ||||
| 
 | ||||
| 	int app; | ||||
| 	int proc; | ||||
| 	char loom[HOST_NAME_MAX]; | ||||
| 	int ncpus; | ||||
| @ -100,9 +103,13 @@ struct ovni_rproc { | ||||
| 	char procdir[PATH_MAX]; | ||||
| 
 | ||||
| 	int ready; | ||||
| 
 | ||||
| 	JSON_Value *meta; | ||||
| }; | ||||
| 
 | ||||
| int ovni_proc_init(char *loom, int proc); | ||||
| int ovni_proc_init(int app, char *loom, int proc); | ||||
| 
 | ||||
| int ovni_proc_fini(); | ||||
| 
 | ||||
| int ovni_thread_init(pid_t tid); | ||||
| 
 | ||||
| @ -120,6 +127,8 @@ int ovni_ev_size(struct ovni_ev *ev); | ||||
| 
 | ||||
| int ovni_payload_size(struct ovni_ev *ev); | ||||
| 
 | ||||
| void ovni_add_cpu(int index, int phyid); | ||||
| 
 | ||||
| /* Set the current clock in the event and queue it */ | ||||
| void ovni_ev(struct ovni_ev *ev); | ||||
| void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize); | ||||
|  | ||||
							
								
								
									
										250
									
								
								parson.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								parson.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,250 @@ | ||||
| /*
 | ||||
|  SPDX-License-Identifier: MIT | ||||
| 
 | ||||
|  Parson 1.1.3 ( http://kgabis.github.com/parson/ )
 | ||||
|  Copyright (c) 2012 - 2021 Krzysztof Gabis | ||||
| 
 | ||||
|  Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  of this software and associated documentation files (the "Software"), to deal | ||||
|  in the Software without restriction, including without limitation the rights | ||||
|  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  copies of the Software, and to permit persons to whom the Software is | ||||
|  furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
|  The above copyright notice and this permission notice shall be included in | ||||
|  all copies or substantial portions of the Software. | ||||
| 
 | ||||
|  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  THE SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #ifndef parson_parson_h | ||||
| #define parson_parson_h | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| #endif | ||||
| 
 | ||||
| #include <stddef.h>   /* size_t */ | ||||
| 
 | ||||
| /* Types and enums */ | ||||
| typedef struct json_object_t JSON_Object; | ||||
| typedef struct json_array_t  JSON_Array; | ||||
| typedef struct json_value_t  JSON_Value; | ||||
| 
 | ||||
| enum json_value_type { | ||||
|     JSONError   = -1, | ||||
|     JSONNull    = 1, | ||||
|     JSONString  = 2, | ||||
|     JSONNumber  = 3, | ||||
|     JSONObject  = 4, | ||||
|     JSONArray   = 5, | ||||
|     JSONBoolean = 6 | ||||
| }; | ||||
| typedef int JSON_Value_Type; | ||||
| 
 | ||||
| enum json_result_t { | ||||
|     JSONSuccess = 0, | ||||
|     JSONFailure = -1 | ||||
| }; | ||||
| typedef int JSON_Status; | ||||
| 
 | ||||
| typedef void * (*JSON_Malloc_Function)(size_t); | ||||
| typedef void   (*JSON_Free_Function)(void *); | ||||
| 
 | ||||
| /* Call only once, before calling any other function from parson API. If not called, malloc and free
 | ||||
|    from stdlib will be used for all allocations */ | ||||
| void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun); | ||||
| 
 | ||||
| /* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
 | ||||
|  This function sets a global setting and is not thread safe. */ | ||||
| void json_set_escape_slashes(int escape_slashes); | ||||
| 
 | ||||
| /* Parses first JSON value in a file, returns NULL in case of error */ | ||||
| JSON_Value * json_parse_file(const char *filename); | ||||
| 
 | ||||
| /* Parses first JSON value in a file and ignores comments (/ * * / and //),
 | ||||
|    returns NULL in case of error */ | ||||
| JSON_Value * json_parse_file_with_comments(const char *filename); | ||||
| 
 | ||||
| /*  Parses first JSON value in a string, returns NULL in case of error */ | ||||
| JSON_Value * json_parse_string(const char *string); | ||||
| 
 | ||||
| /*  Parses first JSON value in a string and ignores comments (/ * * / and //),
 | ||||
|     returns NULL in case of error */ | ||||
| JSON_Value * json_parse_string_with_comments(const char *string); | ||||
| 
 | ||||
| /* Serialization */ | ||||
| size_t      json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ | ||||
| JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); | ||||
| JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); | ||||
| char *      json_serialize_to_string(const JSON_Value *value); | ||||
| 
 | ||||
| /* Pretty serialization */ | ||||
| size_t      json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ | ||||
| JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); | ||||
| JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); | ||||
| char *      json_serialize_to_string_pretty(const JSON_Value *value); | ||||
| 
 | ||||
| void        json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ | ||||
| 
 | ||||
| /* Comparing */ | ||||
| int  json_value_equals(const JSON_Value *a, const JSON_Value *b); | ||||
| 
 | ||||
| /* Validation
 | ||||
|    This is *NOT* JSON Schema. It validates json by checking if object have identically | ||||
|    named fields with matching types. | ||||
|    For example schema {"name":"", "age":0} will validate | ||||
|    {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"}, | ||||
|    but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}. | ||||
|    In case of arrays, only first value in schema is checked against all values in tested array. | ||||
|    Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays, | ||||
|    null validates values of every type. | ||||
|  */ | ||||
| JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value); | ||||
| 
 | ||||
| /*
 | ||||
|  * JSON Object | ||||
|  */ | ||||
| JSON_Value  * json_object_get_value  (const JSON_Object *object, const char *name); | ||||
| const char  * json_object_get_string (const JSON_Object *object, const char *name); | ||||
| size_t        json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ | ||||
| JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); | ||||
| JSON_Array  * json_object_get_array  (const JSON_Object *object, const char *name); | ||||
| double        json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ | ||||
| int           json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ | ||||
| 
 | ||||
| /* dotget functions enable addressing values with dot notation in nested objects,
 | ||||
|  just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). | ||||
|  Because valid names in JSON can contain dots, some values may be inaccessible | ||||
|  this way. */ | ||||
| JSON_Value  * json_object_dotget_value  (const JSON_Object *object, const char *name); | ||||
| const char  * json_object_dotget_string (const JSON_Object *object, const char *name); | ||||
| size_t        json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ | ||||
| JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); | ||||
| JSON_Array  * json_object_dotget_array  (const JSON_Object *object, const char *name); | ||||
| double        json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ | ||||
| int           json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ | ||||
| 
 | ||||
| /* Functions to get available names */ | ||||
| size_t        json_object_get_count   (const JSON_Object *object); | ||||
| const char  * json_object_get_name    (const JSON_Object *object, size_t index); | ||||
| JSON_Value  * json_object_get_value_at(const JSON_Object *object, size_t index); | ||||
| JSON_Value  * json_object_get_wrapping_value(const JSON_Object *object); | ||||
| 
 | ||||
| /* Functions to check if object has a value with a specific name. Returned value is 1 if object has
 | ||||
|  * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ | ||||
| int json_object_has_value        (const JSON_Object *object, const char *name); | ||||
| int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); | ||||
| 
 | ||||
| int json_object_dothas_value        (const JSON_Object *object, const char *name); | ||||
| int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); | ||||
| 
 | ||||
| /* Creates new name-value pair or frees and replaces old value with a new one.
 | ||||
|  * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||
| JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); | ||||
| JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); | ||||
| JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len);  /* length shouldn't include last null character */ | ||||
| JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); | ||||
| JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); | ||||
| JSON_Status json_object_set_null(JSON_Object *object, const char *name); | ||||
| 
 | ||||
| /* Works like dotget functions, but creates whole hierarchy if necessary.
 | ||||
|  * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||
| JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value); | ||||
| JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string); | ||||
| JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ | ||||
| JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number); | ||||
| JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean); | ||||
| JSON_Status json_object_dotset_null(JSON_Object *object, const char *name); | ||||
| 
 | ||||
| /* Frees and removes name-value pair */ | ||||
| JSON_Status json_object_remove(JSON_Object *object, const char *name); | ||||
| 
 | ||||
| /* Works like dotget function, but removes name-value pair only on exact match. */ | ||||
| JSON_Status json_object_dotremove(JSON_Object *object, const char *key); | ||||
| 
 | ||||
| /* Removes all name-value pairs in object */ | ||||
| JSON_Status json_object_clear(JSON_Object *object); | ||||
| 
 | ||||
| /*
 | ||||
|  *JSON Array | ||||
|  */ | ||||
| JSON_Value  * json_array_get_value  (const JSON_Array *array, size_t index); | ||||
| const char  * json_array_get_string (const JSON_Array *array, size_t index); | ||||
| size_t        json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ | ||||
| JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); | ||||
| JSON_Array  * json_array_get_array  (const JSON_Array *array, size_t index); | ||||
| double        json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ | ||||
| int           json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ | ||||
| size_t        json_array_get_count  (const JSON_Array *array); | ||||
| JSON_Value  * json_array_get_wrapping_value(const JSON_Array *array); | ||||
| 
 | ||||
| /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
 | ||||
|  * Order of values in array may change during execution.  */ | ||||
| JSON_Status json_array_remove(JSON_Array *array, size_t i); | ||||
| 
 | ||||
| /* Frees and removes from array value at given index and replaces it with given one.
 | ||||
|  * Does nothing and returns JSONFailure if index doesn't exist. | ||||
|  * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||
| JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); | ||||
| JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); | ||||
| JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */ | ||||
| JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); | ||||
| JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); | ||||
| JSON_Status json_array_replace_null(JSON_Array *array, size_t i); | ||||
| 
 | ||||
| /* Frees and removes all values from array */ | ||||
| JSON_Status json_array_clear(JSON_Array *array); | ||||
| 
 | ||||
| /* Appends new value at the end of array.
 | ||||
|  * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||
| JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value); | ||||
| JSON_Status json_array_append_string(JSON_Array *array, const char *string); | ||||
| JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len); /* length shouldn't include last null character */ | ||||
| JSON_Status json_array_append_number(JSON_Array *array, double number); | ||||
| JSON_Status json_array_append_boolean(JSON_Array *array, int boolean); | ||||
| JSON_Status json_array_append_null(JSON_Array *array); | ||||
| 
 | ||||
| /*
 | ||||
|  *JSON Value | ||||
|  */ | ||||
| JSON_Value * json_value_init_object (void); | ||||
| JSON_Value * json_value_init_array  (void); | ||||
| JSON_Value * json_value_init_string (const char *string); /* copies passed string */ | ||||
| JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ | ||||
| JSON_Value * json_value_init_number (double number); | ||||
| JSON_Value * json_value_init_boolean(int boolean); | ||||
| JSON_Value * json_value_init_null   (void); | ||||
| JSON_Value * json_value_deep_copy   (const JSON_Value *value); | ||||
| void         json_value_free        (JSON_Value *value); | ||||
| 
 | ||||
| JSON_Value_Type json_value_get_type   (const JSON_Value *value); | ||||
| JSON_Object *   json_value_get_object (const JSON_Value *value); | ||||
| JSON_Array  *   json_value_get_array  (const JSON_Value *value); | ||||
| const char  *   json_value_get_string (const JSON_Value *value); | ||||
| size_t          json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ | ||||
| double          json_value_get_number (const JSON_Value *value); | ||||
| int             json_value_get_boolean(const JSON_Value *value); | ||||
| JSON_Value  *   json_value_get_parent (const JSON_Value *value); | ||||
| 
 | ||||
| /* Same as above, but shorter */ | ||||
| JSON_Value_Type json_type   (const JSON_Value *value); | ||||
| JSON_Object *   json_object (const JSON_Value *value); | ||||
| JSON_Array  *   json_array  (const JSON_Value *value); | ||||
| const char  *   json_string (const JSON_Value *value); | ||||
| size_t          json_string_len(const JSON_Value *value); /* doesn't account for last null character */ | ||||
| double          json_number (const JSON_Value *value); | ||||
| int             json_boolean(const JSON_Value *value); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| @ -13,7 +13,7 @@ int main() | ||||
| 	struct ovni_ev ev = {0}; | ||||
| 	int i; | ||||
| 
 | ||||
| 	ovni_proc_init(0, 0); | ||||
| 	ovni_proc_init(0, "test", 0); | ||||
| 	ovni_thread_init(1); | ||||
| 
 | ||||
| 	ovni_ev_set_mcv(&ev, "OB."); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user