1/* Copyright (c) 2013, Dmitriy V. Reshetnikov
2 * Copyright (c) 2013, Vsevolod Stakhov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *       * Redistributions of source code must retain the above copyright
8 *         notice, this list of conditions and the following disclaimer.
9 *       * Redistributions in binary form must reproduce the above copyright
10 *         notice, this list of conditions and the following disclaimer in the
11 *         documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#if defined(_MSC_VER)
26    #include <BaseTsd.h>
27
28    typedef SSIZE_T ssize_t;
29#endif
30
31#include "ucl.h"
32
33void
34ucl_obj_dump (const ucl_object_t *obj, unsigned int shift)
35{
36	int num = shift * 4 + 5;
37	char *pre = (char *) malloc (num * sizeof(char));
38	const ucl_object_t *cur, *tmp;
39	ucl_object_iter_t it = NULL, it_obj = NULL;
40
41	pre[--num] = 0x00;
42	while (num--)
43		pre[num] = 0x20;
44
45	tmp = obj;
46
47	while ((obj = ucl_object_iterate (tmp, &it, false))) {
48		printf ("%sucl object address: %p\n", pre + 4, obj);
49		if (obj->key != NULL) {
50			printf ("%skey: \"%s\"\n", pre, ucl_object_key (obj));
51		}
52		printf ("%sref: %u\n", pre, obj->ref);
53		printf ("%slen: %u\n", pre, obj->len);
54		printf ("%sprev: %p\n", pre, obj->prev);
55		printf ("%snext: %p\n", pre, obj->next);
56		if (obj->type == UCL_OBJECT) {
57			printf ("%stype: UCL_OBJECT\n", pre);
58			printf ("%svalue: %p\n", pre, obj->value.ov);
59			it_obj = NULL;
60			while ((cur = ucl_object_iterate (obj, &it_obj, true))) {
61				ucl_obj_dump (cur, shift + 2);
62			}
63		}
64		else if (obj->type == UCL_ARRAY) {
65			printf ("%stype: UCL_ARRAY\n", pre);
66			printf ("%svalue: %p\n", pre, obj->value.av);
67			it_obj = NULL;
68			while ((cur = ucl_object_iterate (obj, &it_obj, true))) {
69				ucl_obj_dump (cur, shift + 2);
70			}
71		}
72		else if (obj->type == UCL_INT) {
73			printf ("%stype: UCL_INT\n", pre);
74			printf ("%svalue: %jd\n", pre, (intmax_t)ucl_object_toint (obj));
75		}
76		else if (obj->type == UCL_FLOAT) {
77			printf ("%stype: UCL_FLOAT\n", pre);
78			printf ("%svalue: %f\n", pre, ucl_object_todouble (obj));
79		}
80		else if (obj->type == UCL_STRING) {
81			printf ("%stype: UCL_STRING\n", pre);
82			printf ("%svalue: \"%s\"\n", pre, ucl_object_tostring (obj));
83		}
84		else if (obj->type == UCL_BOOLEAN) {
85			printf ("%stype: UCL_BOOLEAN\n", pre);
86			printf ("%svalue: %s\n", pre, ucl_object_tostring_forced (obj));
87		}
88		else if (obj->type == UCL_TIME) {
89			printf ("%stype: UCL_TIME\n", pre);
90			printf ("%svalue: %f\n", pre, ucl_object_todouble (obj));
91		}
92		else if (obj->type == UCL_USERDATA) {
93			printf ("%stype: UCL_USERDATA\n", pre);
94			printf ("%svalue: %p\n", pre, obj->value.ud);
95		}
96	}
97
98	free (pre);
99}
100
101int
102main(int argc, char **argv)
103{
104	const char *fn = NULL;
105	unsigned char *inbuf;
106	struct ucl_parser *parser;
107	int k, ret = 0;
108	ssize_t bufsize, r = 0;
109	ucl_object_t *obj = NULL;
110	const ucl_object_t *par;
111	FILE *in;
112
113	if (argc > 1) {
114		fn = argv[1];
115	}
116
117	if (fn != NULL) {
118		in = fopen (fn, "r");
119		if (in == NULL) {
120			exit (EXIT_FAILURE);
121		}
122	}
123	else {
124		in = stdin;
125	}
126
127	parser = ucl_parser_new (0);
128	inbuf = malloc (BUFSIZ);
129	bufsize = BUFSIZ;
130	r = 0;
131
132	while (!feof (in) && !ferror (in)) {
133		if (r == bufsize) {
134			inbuf = realloc (inbuf, bufsize * 2);
135			bufsize *= 2;
136			if (inbuf == NULL) {
137				perror ("realloc");
138				exit (EXIT_FAILURE);
139			}
140		}
141		r += fread (inbuf + r, 1, bufsize - r, in);
142	}
143
144	if (ferror (in)) {
145		fprintf (stderr, "Failed to read the input file.\n");
146		exit (EXIT_FAILURE);
147	}
148
149	ucl_parser_add_chunk (parser, inbuf, r);
150	fclose (in);
151	if (ucl_parser_get_error(parser)) {
152		printf ("Error occurred: %s\n", ucl_parser_get_error(parser));
153		ret = 1;
154		goto end;
155	}
156
157	obj = ucl_parser_get_object (parser);
158	if (ucl_parser_get_error (parser)) {
159		printf ("Error occurred: %s\n", ucl_parser_get_error(parser));
160		ret = 1;
161		goto end;
162	}
163
164	if (argc > 2) {
165		for (k = 2; k < argc; k++) {
166			printf ("search for \"%s\"... ", argv[k]);
167			par = ucl_object_lookup (obj, argv[k]);
168			printf ("%sfound\n", (par == NULL )?"not ":"");
169			ucl_obj_dump (par, 0);
170		}
171	}
172	else {
173		ucl_obj_dump (obj, 0);
174	}
175
176end:
177	if (parser != NULL) {
178		ucl_parser_free (parser);
179	}
180	if (obj != NULL) {
181		ucl_object_unref (obj);
182	}
183
184	return ret;
185}
186