Improved installation. Updated for inclusion of YAZ header files.
[idzebra-moved-to-github.git] / dict / dcompact.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: dcompact.c,v $
7  * Revision 1.7  1999-11-30 13:48:03  adam
8  * Improved installation. Updated for inclusion of YAZ header files.
9  *
10  * Revision 1.6  1999/09/07 08:13:08  adam
11  * Removed log messages.
12  *
13  * Revision 1.5  1999/05/26 07:49:12  adam
14  * C++ compilation.
15  *
16  * Revision 1.4  1999/05/15 14:36:37  adam
17  * Updated dictionary. Implemented "compression" of dictionary.
18  *
19  * Revision 1.3  1999/05/12 13:08:06  adam
20  * First version of ISAMS.
21  *
22  * Revision 1.2  1999/03/09 16:27:49  adam
23  * More work on SDRKit integration.
24  *
25  * Revision 1.1  1999/03/09 13:07:06  adam
26  * Work on dict_compact routine.
27  *
28  */
29
30 #include <assert.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34
35 #include <yaz/log.h>
36 #include <dict.h>
37
38 static void dict_copy_page(Dict dict, char *to_p, char *from_p, int *map)
39 {
40     int i, slen, no = 0;
41     short *from_indxp, *to_indxp;
42     char *from_info, *to_info;
43     
44     from_indxp = (short*) ((char*) from_p+DICT_bsize(from_p));
45     to_indxp = (short*) ((char*) to_p+DICT_bsize(to_p));
46     to_info = (char*) to_p + DICT_infoffset;
47     for (i = DICT_nodir (from_p); --i >= 0; )
48     {
49         if (*--from_indxp > 0) /* tail string here! */
50         {
51             /* string (Dict_char *) DICT_EOS terminated */
52             /* unsigned char        length of information */
53             /* char *               information */
54
55             from_info = (char*) from_p + *from_indxp;
56             *--to_indxp = to_info - to_p;
57             slen = (dict_strlen((Dict_char*) from_info)+1)*sizeof(Dict_char);
58             memcpy (to_info, from_info, slen);
59             from_info += slen;
60             to_info += slen;
61         }
62         else
63         {
64             Dict_ptr subptr;
65             Dict_char subchar;
66             /* Dict_ptr             subptr */
67             /* Dict_char            sub char */
68             /* unsigned char        length of information */
69             /* char *               information */
70
71             *--to_indxp = -(to_info - to_p);
72             from_info = (char*) from_p - *from_indxp;
73
74             memcpy (&subptr, from_info, sizeof(subptr));
75             subptr = map[subptr];
76             from_info += sizeof(Dict_ptr);
77             memcpy (&subchar, from_info, sizeof(subchar));
78             from_info += sizeof(Dict_char);
79                             
80             memcpy (to_info, &subptr, sizeof(Dict_ptr));
81             to_info += sizeof(Dict_ptr);
82             memcpy (to_info, &subchar, sizeof(Dict_char));
83             to_info += sizeof(Dict_char);
84         }
85         assert (to_info < (char*) to_indxp);
86         slen = *from_info+1;
87         memcpy (to_info, from_info, slen);
88         to_info += slen;
89         ++no;
90     }
91     DICT_size(to_p) = to_info - to_p;
92     DICT_type(to_p) = 0;
93     DICT_nodir(to_p) = no;
94 }
95
96 int dict_copy_compact (BFiles bfs, const char *from_name, const char *to_name)
97 {
98     int no_dir = 0;
99     Dict dict_from, dict_to;
100     int *map, i;
101     dict_from = dict_open (bfs, from_name, 0, 0, 0);
102     if (!dict_from)
103         return -1;
104     map = (int *) xmalloc ((dict_from->head.last+1) * sizeof(*map));
105     for (i = 0; i <= (int) (dict_from->head.last); i++)
106         map[i] = -1;
107     dict_to = dict_open (bfs, to_name, 0, 1, 1);
108     if (!dict_to)
109         return -1;
110     map[0] = 0;
111     map[1] = dict_from->head.page_size;
112     
113     for (i = 1; i < (int) (dict_from->head.last); i++)
114     {
115         void *buf;
116         int size;
117 #if 0
118         logf (LOG_LOG, "map[%d] = %d", i, map[i]);
119 #endif
120         dict_bf_readp (dict_from->dbf, i, &buf);
121         size = ((DICT_size(buf)+sizeof(short)-1)/sizeof(short) +
122                 DICT_nodir(buf))*sizeof(short);
123         map[i+1] = map[i] + size;
124         no_dir += DICT_nodir(buf);
125     }
126 #if 0
127     logf (LOG_LOG, "map[%d] = %d", i, map[i]);
128     logf (LOG_LOG, "nodir = %d", no_dir);
129 #endif
130     dict_to->head.root = map[1];
131     dict_to->head.last = map[i];
132     for (i = 1; i< (int) (dict_from->head.last); i++)
133     {
134         void *old_p, *new_p;
135         dict_bf_readp (dict_from->dbf, i, &old_p);
136
137         logf (LOG_LOG, "dict_bf_newp no=%d size=%d", map[i],
138               map[i+1] - map[i]);
139         dict_bf_newp (dict_to->dbf, map[i], &new_p, map[i+1] - map[i]);
140
141         DICT_type(new_p) = 0;
142         DICT_backptr(new_p) = map[i-1];
143         DICT_bsize(new_p) = map[i+1] - map[i];
144
145         dict_copy_page(dict_from, (char*) new_p, (char*) old_p, map);
146     }
147     dict_close (dict_from);
148     dict_close (dict_to);
149     return 0;
150 }