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