]> mj.ucw.cz Git - eval.git/blob - sherlock/obj2buck.c
Merge branch 'layout'
[eval.git] / sherlock / obj2buck.c
1 /*
2  *      Sherlock Library -- Generating Buckets from Objects
3  *
4  *      (c) 2004, Robert Spalek <robert@ucw.cz>
5  *      (c) 2005, Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "sherlock/sherlock.h"
12 #include "ucw/fastbuf.h"
13 #include "ucw/ff-unicode.h"
14 #include "sherlock/object.h"
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdarg.h>
19
20 static uns use_v33;
21 static int hdr_sep;
22
23 void
24 put_attr_set_type(uns type)
25 {
26   switch (type)
27     {
28     case BUCKET_TYPE_PLAIN:
29       use_v33 = 0;
30       hdr_sep = -1;
31       break;
32     case BUCKET_TYPE_V30:
33       use_v33 = 0;
34       hdr_sep = '\n';
35       break;
36     case BUCKET_TYPE_V33:
37     case BUCKET_TYPE_V33_LIZARD:
38       use_v33 = 1;
39       hdr_sep = 0;
40       break;
41     default:
42       die("Don't know how to generate buckets of type %08x", type);
43     }
44 }
45
46 uns
47 size_attr(uns len)
48 {
49   if (use_v33)
50     {
51       len++;
52       return len + utf8_space(len);
53     }
54   else
55     return len + 2;
56 }
57
58 uns
59 size_object(struct odes *d)
60 {
61   uns sz = 0;
62   for (struct oattr *a=d->attrs; a; a=a->next)
63     for (struct oattr *b=a; b; b=b->same)
64       if (a->attr >= OBJ_ATTR_SON)
65         sz += 3 + size_object(b->son) + 2;
66       else
67         sz += size_attr(strlen(b->val));
68   return sz;
69 }
70
71 inline byte *
72 put_attr(byte *ptr, uns type, byte *val, uns len)
73 {
74   if (use_v33)
75   {
76     ptr = utf8_32_put(ptr, len+1);
77     memcpy(ptr, val, len);
78     ptr += len;
79     *ptr++ = type;
80   }
81   else
82   {
83     *ptr++ = type;
84     memcpy(ptr, val, len);
85     ptr += len;
86     *ptr++ = '\n';
87   }
88   return ptr;
89 }
90
91 byte *
92 put_attr_str(byte *ptr, uns type, byte *val)
93 {
94   return put_attr(ptr, type, val, strlen(val));
95 }
96
97 inline byte *
98 put_attr_vformat(byte *ptr, uns type, byte *mask, va_list va)
99 {
100   uns len;
101   if (use_v33)
102   {
103     len = vsprintf(ptr+1, mask, va);
104     if (len >= 127)
105     {
106       byte tmp[6], *tmp_end = tmp;
107       tmp_end = utf8_32_put(tmp_end, len+1);
108       uns l = tmp_end - tmp;
109       memmove(ptr+l, ptr+1, len);
110       memcpy(ptr, tmp, l);
111       ptr += l + len;
112     }
113     else
114     {
115       *ptr = len+1;
116       ptr += len+1;
117     }
118     *ptr++ = type;
119   }
120   else
121   {
122     *ptr++ = type;
123     len = vsprintf(ptr, mask, va);
124     ptr += len;
125     *ptr++ = '\n';
126   }
127   return ptr;
128 }
129
130 byte *
131 put_attr_format(byte *ptr, uns type, char *mask, ...)
132 {
133   va_list va;
134   va_start(va, mask);
135   byte *ret = put_attr_vformat(ptr, type, mask, va);
136   va_end(va);
137   return ret;
138 }
139
140 byte *
141 put_attr_num(byte *ptr, uns type, uns val)
142 {
143   if (use_v33)
144   {
145     uns len = sprintf(ptr+1, "%d", val) + 1;
146     *ptr = len;
147     ptr += len;
148     *ptr++ = type;
149   }
150   else
151     ptr += sprintf(ptr, "%c%d\n", type, val);
152   return ptr;
153 }
154
155 byte *
156 put_attr_separator(byte *ptr)
157 {
158   if (hdr_sep >= 0)
159     *ptr++ = hdr_sep;
160   return ptr;
161 }
162
163 byte *
164 put_attr_push(byte *ptr, uns type)
165 {
166   byte name = type;
167   return put_attr(ptr, '(', &name, 1);
168 }
169
170 byte *
171 put_attr_pop(byte *ptr)
172 {
173   return put_attr(ptr, ')', NULL, 0);
174 }
175
176 byte *
177 put_object(byte *t, struct odes *d)
178 {
179   for (struct oattr *a=d->attrs; a; a=a->next)
180     for (struct oattr *b=a; b; b=b->same)
181       if (a->attr >= OBJ_ATTR_SON)
182         {
183           t = put_attr_push(t, a->attr - OBJ_ATTR_SON);
184           t = put_object(t, b->son);
185           t = put_attr_pop(t);
186         }
187       else
188         t = put_attr_str(t, a->attr, b->val);
189   return t;
190 }
191
192 inline void
193 bput_attr_large(struct fastbuf *b, uns type, byte *val, uns len)
194 {
195   if (use_v33)
196   {
197     bput_utf8_32(b, len+1);
198     bwrite(b, val, len);
199     bputc(b, type);
200   }
201   else
202   {
203     bputc(b, type);
204     bwrite(b, val, len);
205     bputc(b, '\n');
206   }
207 }
208
209 inline void
210 bput_attr(struct fastbuf *b, uns type, byte *val, uns len)
211 {
212   bput_attr_large(b, type, val, len);
213 }
214
215 void
216 bput_attr_str(struct fastbuf *b, uns type, byte *val)
217 {
218   bput_attr(b, type, val, strlen(val));
219 }
220
221 void
222 bput_attr_vformat(struct fastbuf *b, uns type, byte *mask, va_list va)
223 {
224   int len;
225   if (use_v33)
226   {
227     va_list va2;
228     va_copy(va2, va);
229     len = vsnprintf(NULL, 0, mask, va2);
230     va_end(va2);
231     if (len < 0)
232       die("vsnprintf() does not support size=0");
233     bput_utf8_32(b, len+1);
234     vbprintf(b, mask, va);
235     bputc(b, type);
236   }
237   else
238   {
239     bputc(b, type);
240     len = vbprintf(b, mask, va);
241     bputc(b, '\n');
242   }
243 }
244
245 void
246 bput_attr_format(struct fastbuf *b, uns type, char *mask, ...)
247 {
248   va_list va;
249   va_start(va, mask);
250   bput_attr_vformat(b, type, mask, va);
251   va_end(va);
252 }
253
254 void
255 bput_attr_num(struct fastbuf *b, uns type, uns val)
256 {
257   if (use_v33)
258   {
259     byte tmp[12];
260     uns len = sprintf(tmp, "%d", val);
261     bputc(b, len+1);
262     bwrite(b, tmp, len);
263     bputc(b, type);
264   }
265   else
266     bprintf(b, "%c%d\n", type, val);
267 }
268
269 void
270 bput_attr_separator(struct fastbuf *b)
271 {
272   if (hdr_sep >= 0)
273     bputc(b, hdr_sep);
274 }
275
276 void
277 bput_attr_push(struct fastbuf *b, uns type)
278 {
279   byte name = type;
280   bput_attr(b, '(', &name, 1);
281 }
282
283 void
284 bput_attr_pop(struct fastbuf *b)
285 {
286   bput_attr(b, ')', NULL, 0);
287 }
288
289 static inline void
290 do_bput_oattr(struct fastbuf *f, struct oattr *a)
291 {
292   for(struct oattr *b=a; b; b=b->same)
293     if (a->attr >= OBJ_ATTR_SON)
294       {
295         bput_attr_push(f, a->attr - OBJ_ATTR_SON);
296         bput_object(f, b->son);
297         bput_attr_pop(f);
298       }
299     else
300       {
301 #ifdef DEBUG_ASSERTS
302         byte *z;
303         for (z = b->val; *z; z++)
304           if (*z < ' ' && *z != '\t')
305             {
306               log(L_ERROR, "obj_write: Found non-ASCII character %02x in %c%s", *z, a->attr, b->val);
307               ASSERT(0);
308             }
309 #endif
310         bput_attr_str(f, a->attr, b->val);
311       }
312 }
313
314 void
315 bput_oattr(struct fastbuf *f, struct oattr *a)
316 {
317   if (a)
318     do_bput_oattr(f, a);
319 }
320
321 void
322 bput_object(struct fastbuf *f, struct odes *d)
323 {
324   for(struct oattr *a=d->attrs; a; a=a->next)
325     do_bput_oattr(f, a);
326 }
327
328 static inline void
329 do_bput_oattr_nocheck(struct fastbuf *f, struct oattr *a)
330 {
331   for(struct oattr *b=a; b; b=b->same)
332     if (a->attr >= OBJ_ATTR_SON)
333       {
334         bput_attr_push(f, a->attr - OBJ_ATTR_SON);
335         bput_object_nocheck(f, b->son);
336         bput_attr_pop(f);
337       }
338     else
339       bput_attr_large(f, a->attr, b->val, strlen(b->val));
340 }
341
342 void
343 bput_oattr_nocheck(struct fastbuf *f, struct oattr *a)
344 {
345   if (a)
346     do_bput_oattr_nocheck(f, a);
347 }
348
349 void
350 bput_object_nocheck(struct fastbuf *f, struct odes *d)
351 {
352   for(struct oattr *a=d->attrs; a; a=a->next)
353     do_bput_oattr_nocheck(f, a);
354 }
355
356 void
357 obj_write(struct fastbuf *b, struct odes *o, uns bucket_type)
358 {
359   put_attr_set_type(bucket_type);
360   bput_object(b, o);
361 }
362
363 void
364 obj_write_nocheck(struct fastbuf *b, struct odes *o, uns bucket_type)
365 {
366   put_attr_set_type(bucket_type);
367   bput_object_nocheck(b, o);
368 }