Enable ATTR_INTLIST to contain zeros. Use the same encoding as IDARRAY.
[platform/upstream/libsolv.git] / src / attr_store_p.h
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #ifndef ATTR_STORE_P_H
9 #define ATTR_STORE_P_H
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15 typedef struct
16 {
17   Id key;
18   union {
19     unsigned int i[2];
20     const char *str;
21     int *intlist;
22     LocalId *localids;
23   } v;
24 } LongNV;
25
26 #define BLOB_PAGEBITS 15
27 #define BLOB_PAGESIZE (1 << BLOB_PAGEBITS)
28
29 typedef struct _Attrblobpage
30 {
31   /* mapped_at == -1  --> not loaded, otherwise offset into
32      store->blob_store.  The size of the mapping is BLOB_PAGESIZE
33      except for the last page.  */
34   unsigned int mapped_at;
35   long file_offset;
36   /* file_size == 0 means the page is not backed by some file storage.
37      Otherwise it is L*2+(compressed ? 1 : 0), with L being the data
38      length.  */
39   long file_size;
40 } Attrblobpage;
41
42 typedef struct _Dir
43 {
44   unsigned parent;
45   unsigned child;
46   unsigned sibling;
47   Id name;
48 } Dir;
49
50 struct _Attrstore
51 {
52   Pool *pool;
53   unsigned int entries;
54   LongNV **attrs;
55   char *blob_store;
56   unsigned int blob_next_free;
57   Attrblobpage *pages;
58   unsigned int num_pages;
59   FILE *file;
60   /* mapped[i] is zero if nothing is mapped at logical page I,
61      otherwise it contains the pagenumber plus one (of the mapped page).  */
62   unsigned int *mapped;
63   unsigned int nmapped, ncanmap;
64   unsigned int rr_counter;
65
66   Stringpool ss;
67
68   struct Dirtree {
69     Dir *dirs;
70     unsigned ndirs;
71     Stringpool ss;
72     unsigned *dirstack;
73     unsigned ndirstack, dirstack_size;
74   } dirtree;
75
76   /* A space efficient in memory representation.  It's read-only.  */
77   /* flat_attrs[ent2attr[i]] are the attrs for entity i.  */
78   unsigned int *ent2attr;
79   unsigned char *flat_attrs;
80   unsigned int attr_next_free;
81
82   struct {
83     Id name;
84     unsigned type;
85     unsigned size;
86   } *keys;
87   unsigned nkeys;
88   Id *schemata;
89   unsigned *schemaofs;
90   unsigned nschemata, szschemata;
91
92   unsigned int packed:1;
93 };
94
95 void add_attr_from_file (Attrstore *s, unsigned entry, Id name, int type, Id *idmap, unsigned maxid, FILE *fp);
96 void read_or_setup_pages (FILE *fp, Attrstore *s);
97
98 #define get_num(ptr,val) do { \
99   typedef int __wrong_buf__[(1-sizeof((ptr)[0])) * (sizeof((ptr)[0])-1)];\
100   val = 0; \
101   while (1) { \
102     unsigned char __c = *((ptr)++); \
103     (val) = ((val) << 7) | (__c & 0x7F); \
104     if ((__c & 0x80) == 0) \
105       break; \
106   } \
107 } while (0)
108
109 typedef struct {
110   unsigned char *attrs;
111   Id *schema;
112   unsigned char *attrs_next;
113   Id name;
114   unsigned type;
115
116   /* The following fields could be a union, but if we do that GCC
117      doesn't scalarize these fields anymore, hence real memory accesses
118      would remain, so don't do that.  */
119   int as_int;
120   Id as_id;
121   unsigned int as_chunk[2];
122   const char *as_string;
123   const unsigned char *as_numlist;
124 } attr_iterator;
125
126 static inline void
127 ai_init (Attrstore *s, unsigned int i, attr_iterator *ai)
128 {
129   ai->attrs = s->flat_attrs + s->ent2attr[i];
130   unsigned int this_schema;
131   get_num (ai->attrs, this_schema);
132   ai->schema = s->schemata + s->schemaofs[this_schema];
133
134   /* Initialize all fields so we get no uninit warnings later.
135      Don't use memset() to initialize this structure, it would make
136      GCC not scalarize it.  */
137   ai->as_int = 0;
138   ai->as_id = 0;
139   ai->as_chunk[0] = ai->as_chunk[1] = 0;
140   ai->as_string = 0;
141   ai->as_numlist = 0;
142 }
143
144 static inline int
145 ai_step (Attrstore *s, attr_iterator *ai)
146 {
147   Id key = *(ai->schema);
148   if (!key)
149     return 0;
150   ai->name = s->keys[key].name;
151   ai->type = s->keys[key].type;
152   ai->attrs_next = ai->attrs;
153   switch (ai->type)
154     {
155     case TYPE_VOID:
156       /* No data.  */
157       break;
158     case TYPE_ATTR_INT:
159       {
160         int val;
161         get_num (ai->attrs_next, val);
162         ai->as_int = val;
163         break;
164       }
165     case TYPE_ATTR_CHUNK:
166       {
167         unsigned int val1, val2;
168         get_num (ai->attrs_next, val1);
169         ai->as_chunk[0] = val1;
170         get_num (ai->attrs_next, val2);
171         ai->as_chunk[1] = val2;
172         break;
173       }
174     case TYPE_ATTR_STRING:
175       {
176         ai->as_string = (const char *) ai->attrs_next;
177         ai->attrs_next += strlen ((const char*)ai->attrs_next) + 1;
178         break;
179       }
180     case TYPE_ATTR_INTLIST:
181       {
182         ai->as_numlist = ai->attrs_next;
183         while (1)
184           {
185             int val;
186             get_num (ai->attrs_next, val);
187             if (!(val & 64))
188               break;
189           }
190         break;
191       }
192     case TYPE_ATTR_LOCALIDS:
193       {
194         ai->as_numlist = ai->attrs_next;
195         while (1)
196           {
197             Id val;
198             get_num (ai->attrs_next, val);
199             if (!val)
200               break;
201           }
202         break;
203       }
204     default:
205       /* ??? Convert TYPE_ATTR_SPECIAL_* to _INT type with the right value? */
206       break;
207     }
208   return 1;
209 }
210
211 #define FOR_ATTRS(s,i,ai) \
212   for (ai_init (s, i, ai); ai_step (s, ai); (ai)->schema++,(ai)->attrs = (ai)->attrs_next)
213
214 #ifdef __cplusplus
215 }
216 #endif
217
218 #endif