xref: /freebsd/lib/libc/iconv/citrus_pivot_factory.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
1ad30f8e7SGabor Kovesdan /* $NetBSD: citrus_pivot_factory.c,v 1.7 2009/04/12 14:20:19 lukem Exp $ */
2ad30f8e7SGabor Kovesdan 
3ad30f8e7SGabor Kovesdan /*-
4*d915a14eSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
5*d915a14eSPedro F. Giffuni  *
6ad30f8e7SGabor Kovesdan  * Copyright (c)2003 Citrus Project,
7ad30f8e7SGabor Kovesdan  * All rights reserved.
8ad30f8e7SGabor Kovesdan  *
9ad30f8e7SGabor Kovesdan  * Redistribution and use in source and binary forms, with or without
10ad30f8e7SGabor Kovesdan  * modification, are permitted provided that the following conditions
11ad30f8e7SGabor Kovesdan  * are met:
12ad30f8e7SGabor Kovesdan  * 1. Redistributions of source code must retain the above copyright
13ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer.
14ad30f8e7SGabor Kovesdan  * 2. Redistributions in binary form must reproduce the above copyright
15ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer in the
16ad30f8e7SGabor Kovesdan  *    documentation and/or other materials provided with the distribution.
17ad30f8e7SGabor Kovesdan  *
18ad30f8e7SGabor Kovesdan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ad30f8e7SGabor Kovesdan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ad30f8e7SGabor Kovesdan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ad30f8e7SGabor Kovesdan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ad30f8e7SGabor Kovesdan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ad30f8e7SGabor Kovesdan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ad30f8e7SGabor Kovesdan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ad30f8e7SGabor Kovesdan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ad30f8e7SGabor Kovesdan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ad30f8e7SGabor Kovesdan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ad30f8e7SGabor Kovesdan  * SUCH DAMAGE.
29ad30f8e7SGabor Kovesdan  */
30ad30f8e7SGabor Kovesdan 
31ad30f8e7SGabor Kovesdan #include <sys/queue.h>
32ad30f8e7SGabor Kovesdan 
33ad30f8e7SGabor Kovesdan #include <assert.h>
34ad30f8e7SGabor Kovesdan #include <ctype.h>
35ad30f8e7SGabor Kovesdan #include <errno.h>
36ad30f8e7SGabor Kovesdan #include <limits.h>
37ad30f8e7SGabor Kovesdan #include <stdio.h>
38ad30f8e7SGabor Kovesdan #include <stdlib.h>
39ad30f8e7SGabor Kovesdan #include <string.h>
40ad30f8e7SGabor Kovesdan 
41ad30f8e7SGabor Kovesdan #include "citrus_namespace.h"
42ad30f8e7SGabor Kovesdan #include "citrus_region.h"
43ad30f8e7SGabor Kovesdan #include "citrus_bcs.h"
44ad30f8e7SGabor Kovesdan #include "citrus_db_factory.h"
45ad30f8e7SGabor Kovesdan #include "citrus_db_hash.h"
46ad30f8e7SGabor Kovesdan #include "citrus_pivot_file.h"
47ad30f8e7SGabor Kovesdan #include "citrus_pivot_factory.h"
48ad30f8e7SGabor Kovesdan 
49ad30f8e7SGabor Kovesdan struct src_entry {
50ad30f8e7SGabor Kovesdan 	char				*se_name;
51ad30f8e7SGabor Kovesdan 	struct _citrus_db_factory	*se_df;
52ad30f8e7SGabor Kovesdan 	STAILQ_ENTRY(src_entry)		 se_entry;
53ad30f8e7SGabor Kovesdan };
54ad30f8e7SGabor Kovesdan STAILQ_HEAD(src_head, src_entry);
55ad30f8e7SGabor Kovesdan 
56ad30f8e7SGabor Kovesdan static int
find_src(struct src_head * sh,struct src_entry ** rse,const char * name)57ad30f8e7SGabor Kovesdan find_src(struct src_head *sh, struct src_entry **rse, const char *name)
58ad30f8e7SGabor Kovesdan {
59ad30f8e7SGabor Kovesdan 	int ret;
60ad30f8e7SGabor Kovesdan 	struct src_entry *se;
61ad30f8e7SGabor Kovesdan 
62ad30f8e7SGabor Kovesdan 	STAILQ_FOREACH(se, sh, se_entry) {
63ad30f8e7SGabor Kovesdan 		if (_bcs_strcasecmp(se->se_name, name) == 0) {
64ad30f8e7SGabor Kovesdan 			*rse = se;
65ad30f8e7SGabor Kovesdan 			return (0);
66ad30f8e7SGabor Kovesdan 		}
67ad30f8e7SGabor Kovesdan 	}
68ad30f8e7SGabor Kovesdan 	se = malloc(sizeof(*se));
69ad30f8e7SGabor Kovesdan 	if (se == NULL)
70ad30f8e7SGabor Kovesdan 		return (errno);
71ad30f8e7SGabor Kovesdan 	se->se_name = strdup(name);
72ad30f8e7SGabor Kovesdan 	if (se->se_name == NULL) {
73ad30f8e7SGabor Kovesdan 		ret = errno;
74ad30f8e7SGabor Kovesdan 		free(se);
75ad30f8e7SGabor Kovesdan 		return (ret);
76ad30f8e7SGabor Kovesdan 	}
77ad30f8e7SGabor Kovesdan 	ret = _db_factory_create(&se->se_df, &_db_hash_std, NULL);
78ad30f8e7SGabor Kovesdan 	if (ret) {
79ad30f8e7SGabor Kovesdan 		free(se->se_name);
80ad30f8e7SGabor Kovesdan 		free(se);
81ad30f8e7SGabor Kovesdan 		return (ret);
82ad30f8e7SGabor Kovesdan 	}
83ad30f8e7SGabor Kovesdan 	STAILQ_INSERT_TAIL(sh, se, se_entry);
84ad30f8e7SGabor Kovesdan 	*rse = se;
85ad30f8e7SGabor Kovesdan 
86ad30f8e7SGabor Kovesdan 	return (0);
87ad30f8e7SGabor Kovesdan }
88ad30f8e7SGabor Kovesdan 
89ad30f8e7SGabor Kovesdan static void
free_src(struct src_head * sh)90ad30f8e7SGabor Kovesdan free_src(struct src_head *sh)
91ad30f8e7SGabor Kovesdan {
92ad30f8e7SGabor Kovesdan 	struct src_entry *se;
93ad30f8e7SGabor Kovesdan 
94ad30f8e7SGabor Kovesdan 	while ((se = STAILQ_FIRST(sh)) != NULL) {
95ad30f8e7SGabor Kovesdan 		STAILQ_REMOVE_HEAD(sh, se_entry);
96ad30f8e7SGabor Kovesdan 		_db_factory_free(se->se_df);
97ad30f8e7SGabor Kovesdan 		free(se->se_name);
98ad30f8e7SGabor Kovesdan 		free(se);
99ad30f8e7SGabor Kovesdan 	}
100ad30f8e7SGabor Kovesdan }
101ad30f8e7SGabor Kovesdan 
102ad30f8e7SGabor Kovesdan 
103ad30f8e7SGabor Kovesdan #define T_COMM '#'
104ad30f8e7SGabor Kovesdan static int
convert_line(struct src_head * sh,const char * line,size_t len)105ad30f8e7SGabor Kovesdan convert_line(struct src_head *sh, const char *line, size_t len)
106ad30f8e7SGabor Kovesdan {
107ad30f8e7SGabor Kovesdan 	struct src_entry *se;
108ad30f8e7SGabor Kovesdan 	const char *p;
109ad30f8e7SGabor Kovesdan 	char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX];
110ad30f8e7SGabor Kovesdan 	char *ep;
111ad30f8e7SGabor Kovesdan 	uint32_t val;
112ad30f8e7SGabor Kovesdan 	int ret;
113ad30f8e7SGabor Kovesdan 
114ad30f8e7SGabor Kovesdan 	se = NULL;
115ad30f8e7SGabor Kovesdan 
116ad30f8e7SGabor Kovesdan 	/* cut off trailing comment */
117ad30f8e7SGabor Kovesdan 	p = memchr(line, T_COMM, len);
118ad30f8e7SGabor Kovesdan 	if (p)
119ad30f8e7SGabor Kovesdan 		len = p - line;
120ad30f8e7SGabor Kovesdan 
121ad30f8e7SGabor Kovesdan 	/* key1 */
122ad30f8e7SGabor Kovesdan 	line = _bcs_skip_ws_len(line, &len);
123ad30f8e7SGabor Kovesdan 	if (len == 0)
124ad30f8e7SGabor Kovesdan 		return (0);
125ad30f8e7SGabor Kovesdan 	p = _bcs_skip_nonws_len(line, &len);
126ad30f8e7SGabor Kovesdan 	if (p == line)
127ad30f8e7SGabor Kovesdan 		return (0);
128ad30f8e7SGabor Kovesdan 	snprintf(key1, sizeof(key1), "%.*s", (int)(p - line), line);
129ad30f8e7SGabor Kovesdan 
130ad30f8e7SGabor Kovesdan 	/* key2 */
131ad30f8e7SGabor Kovesdan 	line = _bcs_skip_ws_len(p, &len);
132ad30f8e7SGabor Kovesdan 	if (len == 0)
133ad30f8e7SGabor Kovesdan 		return (0);
134ad30f8e7SGabor Kovesdan 	p = _bcs_skip_nonws_len(line, &len);
135ad30f8e7SGabor Kovesdan 	if (p == line)
136ad30f8e7SGabor Kovesdan 		return (0);
137ad30f8e7SGabor Kovesdan 	snprintf(key2, sizeof(key2), "%.*s", (int)(p - line), line);
138ad30f8e7SGabor Kovesdan 
139ad30f8e7SGabor Kovesdan 	/* data */
140ad30f8e7SGabor Kovesdan 	line = _bcs_skip_ws_len(p, &len);
141ad30f8e7SGabor Kovesdan 	_bcs_trunc_rws_len(line, &len);
142ad30f8e7SGabor Kovesdan 	snprintf(data, sizeof(data), "%.*s", (int)len, line);
143ad30f8e7SGabor Kovesdan 	val = strtoul(data, &ep, 0);
144ad30f8e7SGabor Kovesdan 	if (*ep != '\0')
145ad30f8e7SGabor Kovesdan 		return (EFTYPE);
146ad30f8e7SGabor Kovesdan 
147ad30f8e7SGabor Kovesdan 	/* insert to DB */
148ad30f8e7SGabor Kovesdan 	ret = find_src(sh, &se, key1);
149ad30f8e7SGabor Kovesdan 	if (ret)
150ad30f8e7SGabor Kovesdan 		return (ret);
151ad30f8e7SGabor Kovesdan 
152ad30f8e7SGabor Kovesdan 	return (_db_factory_add32_by_s(se->se_df, key2, val));
153ad30f8e7SGabor Kovesdan }
154ad30f8e7SGabor Kovesdan 
155ad30f8e7SGabor Kovesdan static int
dump_db(struct src_head * sh,struct _region * r)156ad30f8e7SGabor Kovesdan dump_db(struct src_head *sh, struct _region *r)
157ad30f8e7SGabor Kovesdan {
158ad30f8e7SGabor Kovesdan 	struct _db_factory *df;
159ad30f8e7SGabor Kovesdan 	struct src_entry *se;
160ad30f8e7SGabor Kovesdan 	struct _region subr;
161ad30f8e7SGabor Kovesdan 	void *ptr;
162ad30f8e7SGabor Kovesdan 	size_t size;
163ad30f8e7SGabor Kovesdan 	int ret;
164ad30f8e7SGabor Kovesdan 
165ad30f8e7SGabor Kovesdan 	ret = _db_factory_create(&df, &_db_hash_std, NULL);
166ad30f8e7SGabor Kovesdan 	if (ret)
167ad30f8e7SGabor Kovesdan 		return (ret);
168ad30f8e7SGabor Kovesdan 
169ad30f8e7SGabor Kovesdan 	STAILQ_FOREACH(se, sh, se_entry) {
170ad30f8e7SGabor Kovesdan 		size = _db_factory_calc_size(se->se_df);
171ad30f8e7SGabor Kovesdan 		ptr = malloc(size);
172ad30f8e7SGabor Kovesdan 		if (ptr == NULL)
173ad30f8e7SGabor Kovesdan 			goto quit;
174ad30f8e7SGabor Kovesdan 		_region_init(&subr, ptr, size);
175ad30f8e7SGabor Kovesdan 		ret = _db_factory_serialize(se->se_df, _CITRUS_PIVOT_SUB_MAGIC,
176ad30f8e7SGabor Kovesdan 		    &subr);
177ad30f8e7SGabor Kovesdan 		if (ret)
178ad30f8e7SGabor Kovesdan 			goto quit;
179ad30f8e7SGabor Kovesdan 		ret = _db_factory_add_by_s(df, se->se_name, &subr, 1);
180ad30f8e7SGabor Kovesdan 		if (ret)
181ad30f8e7SGabor Kovesdan 			goto quit;
182ad30f8e7SGabor Kovesdan 	}
183ad30f8e7SGabor Kovesdan 
184ad30f8e7SGabor Kovesdan 	size = _db_factory_calc_size(df);
185ad30f8e7SGabor Kovesdan 	ptr = malloc(size);
186ad30f8e7SGabor Kovesdan 	if (ptr == NULL)
187ad30f8e7SGabor Kovesdan 		goto quit;
188ad30f8e7SGabor Kovesdan 	_region_init(r, ptr, size);
189ad30f8e7SGabor Kovesdan 
190ad30f8e7SGabor Kovesdan 	ret = _db_factory_serialize(df, _CITRUS_PIVOT_MAGIC, r);
191ad30f8e7SGabor Kovesdan 	ptr = NULL;
192ad30f8e7SGabor Kovesdan 
193ad30f8e7SGabor Kovesdan quit:
194ad30f8e7SGabor Kovesdan 	free(ptr);
195ad30f8e7SGabor Kovesdan 	_db_factory_free(df);
196ad30f8e7SGabor Kovesdan 	return (ret);
197ad30f8e7SGabor Kovesdan }
198ad30f8e7SGabor Kovesdan 
199ad30f8e7SGabor Kovesdan int
_citrus_pivot_factory_convert(FILE * out,FILE * in)200ad30f8e7SGabor Kovesdan _citrus_pivot_factory_convert(FILE *out, FILE *in)
201ad30f8e7SGabor Kovesdan {
202ad30f8e7SGabor Kovesdan 	struct src_head sh;
203ad30f8e7SGabor Kovesdan 	struct _region r;
204ad30f8e7SGabor Kovesdan 	char *line;
205ad30f8e7SGabor Kovesdan 	size_t size;
206ad30f8e7SGabor Kovesdan 	int ret;
207ad30f8e7SGabor Kovesdan 
208ad30f8e7SGabor Kovesdan 	STAILQ_INIT(&sh);
209ad30f8e7SGabor Kovesdan 
210ad30f8e7SGabor Kovesdan 	while ((line = fgetln(in, &size)) != NULL)
211ad30f8e7SGabor Kovesdan 		if ((ret = convert_line(&sh, line, size))) {
212ad30f8e7SGabor Kovesdan 			free_src(&sh);
213ad30f8e7SGabor Kovesdan 			return (ret);
214ad30f8e7SGabor Kovesdan 		}
215ad30f8e7SGabor Kovesdan 
216ad30f8e7SGabor Kovesdan 	ret = dump_db(&sh, &r);
217ad30f8e7SGabor Kovesdan 	free_src(&sh);
218ad30f8e7SGabor Kovesdan 	if (ret)
219ad30f8e7SGabor Kovesdan 		return (ret);
220ad30f8e7SGabor Kovesdan 
221ad30f8e7SGabor Kovesdan 	if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1)
222ad30f8e7SGabor Kovesdan 		return (errno);
223ad30f8e7SGabor Kovesdan 
224ad30f8e7SGabor Kovesdan 	return (0);
225ad30f8e7SGabor Kovesdan }
226