715b0a256fec76d04202ddecccf4135b257c5df3
[idzebra-moved-to-github.git] / dict / dcompact.c
1 /* $Id: dcompact.c,v 1.10 2004-11-19 10:26:54 heikki Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #include <yaz/ylog.h>
31 #include <dict.h>
32
33 static void dict_copy_page(Dict dict, char *to_p, char *from_p, int *map)
34 {
35     int i, slen, no = 0;
36     short *from_indxp, *to_indxp;
37     char *from_info, *to_info;
38     
39     from_indxp = (short*) ((char*) from_p+DICT_bsize(from_p));
40     to_indxp = (short*) ((char*) to_p+DICT_bsize(to_p));
41     to_info = (char*) to_p + DICT_infoffset;
42     for (i = DICT_nodir (from_p); --i >= 0; )
43     {
44         if (*--from_indxp > 0) /* tail string here! */
45         {
46             /* string (Dict_char *) DICT_EOS terminated */
47             /* unsigned char        length of information */
48             /* char *               information */
49
50             from_info = (char*) from_p + *from_indxp;
51             *--to_indxp = to_info - to_p;
52             slen = (dict_strlen((Dict_char*) from_info)+1)*sizeof(Dict_char);
53             memcpy (to_info, from_info, slen);
54             from_info += slen;
55             to_info += slen;
56         }
57         else
58         {
59             Dict_ptr subptr;
60             Dict_char subchar;
61             /* Dict_ptr             subptr */
62             /* Dict_char            sub char */
63             /* unsigned char        length of information */
64             /* char *               information */
65
66             *--to_indxp = -(to_info - to_p);
67             from_info = (char*) from_p - *from_indxp;
68
69             memcpy (&subptr, from_info, sizeof(subptr));
70             subptr = map[subptr];
71             from_info += sizeof(Dict_ptr);
72             memcpy (&subchar, from_info, sizeof(subchar));
73             from_info += sizeof(Dict_char);
74                             
75             memcpy (to_info, &subptr, sizeof(Dict_ptr));
76             to_info += sizeof(Dict_ptr);
77             memcpy (to_info, &subchar, sizeof(Dict_char));
78             to_info += sizeof(Dict_char);
79         }
80         assert (to_info < (char*) to_indxp);
81         slen = *from_info+1;
82         memcpy (to_info, from_info, slen);
83         to_info += slen;
84         ++no;
85     }
86     DICT_size(to_p) = to_info - to_p;
87     DICT_type(to_p) = 0;
88     DICT_nodir(to_p) = no;
89 }
90
91 int dict_copy_compact (BFiles bfs, const char *from_name, const char *to_name)
92 {
93     int no_dir = 0;
94     Dict dict_from, dict_to;
95     int *map, i;
96     dict_from = dict_open (bfs, from_name, 0, 0, 0, 4096);
97     if (!dict_from)
98         return -1;
99     map = (int *) xmalloc ((dict_from->head.last+1) * sizeof(*map));
100     for (i = 0; i <= (int) (dict_from->head.last); i++)
101         map[i] = -1;
102     dict_to = dict_open (bfs, to_name, 0, 1, 1, 4096);
103     if (!dict_to)
104         return -1;
105     map[0] = 0;
106     map[1] = dict_from->head.page_size;
107     
108     for (i = 1; i < (int) (dict_from->head.last); i++)
109     {
110         void *buf;
111         int size;
112 #if 0
113         yaz_log (YLOG_LOG, "map[%d] = %d", i, map[i]);
114 #endif
115         dict_bf_readp (dict_from->dbf, i, &buf);
116         size = ((DICT_size(buf)+sizeof(short)-1)/sizeof(short) +
117                 DICT_nodir(buf))*sizeof(short);
118         map[i+1] = map[i] + size;
119         no_dir += DICT_nodir(buf);
120     }
121 #if 0
122     yaz_log (YLOG_LOG, "map[%d] = %d", i, map[i]);
123     yaz_log (YLOG_LOG, "nodir = %d", no_dir);
124 #endif
125     dict_to->head.root = map[1];
126     dict_to->head.last = map[i];
127     for (i = 1; i< (int) (dict_from->head.last); i++)
128     {
129         void *old_p, *new_p;
130         dict_bf_readp (dict_from->dbf, i, &old_p);
131
132         yaz_log (YLOG_LOG, "dict_bf_newp no=%d size=%d", map[i],
133               map[i+1] - map[i]);
134         dict_bf_newp (dict_to->dbf, map[i], &new_p, map[i+1] - map[i]);
135
136         DICT_type(new_p) = 0;
137         DICT_backptr(new_p) = map[i-1];
138         DICT_bsize(new_p) = map[i+1] - map[i];
139
140         dict_copy_page(dict_from, (char*) new_p, (char*) old_p, map);
141     }
142     dict_close (dict_from);
143     dict_close (dict_to);
144     return 0;
145 }