diff options
Diffstat (limited to 'tools/perf/pmu-events/json.c')
| -rw-r--r-- | tools/perf/pmu-events/json.c | 162 | 
1 files changed, 162 insertions, 0 deletions
diff --git a/tools/perf/pmu-events/json.c b/tools/perf/pmu-events/json.c new file mode 100644 index 000000000000..f67bbb0aa36e --- /dev/null +++ b/tools/perf/pmu-events/json.c @@ -0,0 +1,162 @@ +/* Parse JSON files using the JSMN parser. */ + +/* + * Copyright (c) 2014, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include "jsmn.h" +#include "json.h" +#include <linux/kernel.h> + + +static char *mapfile(const char *fn, size_t *size) +{ +	unsigned ps = sysconf(_SC_PAGESIZE); +	struct stat st; +	char *map = NULL; +	int err; +	int fd = open(fn, O_RDONLY); + +	if (fd < 0 && verbose && fn) { +		pr_err("Error opening events file '%s': %s\n", fn, +				strerror(errno)); +	} + +	if (fd < 0) +		return NULL; +	err = fstat(fd, &st); +	if (err < 0) +		goto out; +	*size = st.st_size; +	map = mmap(NULL, +		   (st.st_size + ps - 1) & ~(ps - 1), +		   PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); +	if (map == MAP_FAILED) +		map = NULL; +out: +	close(fd); +	return map; +} + +static void unmapfile(char *map, size_t size) +{ +	unsigned ps = sysconf(_SC_PAGESIZE); +	munmap(map, roundup(size, ps)); +} + +/* + * Parse json file using jsmn. Return array of tokens, + * and mapped file. Caller needs to free array. + */ +jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len) +{ +	jsmn_parser parser; +	jsmntok_t *tokens; +	jsmnerr_t res; +	unsigned sz; + +	*map = mapfile(fn, size); +	if (!*map) +		return NULL; +	/* Heuristic */ +	sz = *size * 16; +	tokens = malloc(sz); +	if (!tokens) +		goto error; +	jsmn_init(&parser); +	res = jsmn_parse(&parser, *map, *size, tokens, +			 sz / sizeof(jsmntok_t)); +	if (res != JSMN_SUCCESS) { +		pr_err("%s: json error %s\n", fn, jsmn_strerror(res)); +		goto error_free; +	} +	if (len) +		*len = parser.toknext; +	return tokens; +error_free: +	free(tokens); +error: +	unmapfile(*map, *size); +	return NULL; +} + +void free_json(char *map, size_t size, jsmntok_t *tokens) +{ +	free(tokens); +	unmapfile(map, size); +} + +static int countchar(char *map, char c, int end) +{ +	int i; +	int count = 0; +	for (i = 0; i < end; i++) +		if (map[i] == c) +			count++; +	return count; +} + +/* Return line number of a jsmn token */ +int json_line(char *map, jsmntok_t *t) +{ +	return countchar(map, '\n', t->start) + 1; +} + +static const char * const jsmn_types[] = { +	[JSMN_PRIMITIVE] = "primitive", +	[JSMN_ARRAY] = "array", +	[JSMN_OBJECT] = "object", +	[JSMN_STRING] = "string" +}; + +#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?") + +/* Return type name of a jsmn token */ +const char *json_name(jsmntok_t *t) +{ +	return LOOKUP(jsmn_types, t->type); +} + +int json_len(jsmntok_t *t) +{ +	return t->end - t->start; +} + +/* Is string t equal to s? */ +int json_streq(char *map, jsmntok_t *t, const char *s) +{ +	unsigned len = json_len(t); +	return len == strlen(s) && !strncasecmp(map + t->start, s, len); +}  |