5 #cgo CFLAGS: -std=gnu99 -O3
10 static __attribute__((hot)) const uint32_t uvarint(const uint8_t *restrict*data) {
12 if ((b = *((*data)++)) < 0x80) {
14 } else if ((c = *((*data)++)) < 0x80) {
15 return (uint32_t) (b & 0x7F) |
17 } else if ((d = *((*data)++)) < 0x80) {
18 return (uint32_t) (b & 0x7F) |
19 (uint32_t)((c & 0x7F) << 7) |
22 return (uint32_t) (b & 0x7F) |
23 (uint32_t)((c & 0x7F) << 7) |
24 (uint32_t)((d & 0x7F) << 14) |
25 ((uint32_t)(*((*data)++)) << 21);
29 // NB: This is a fragile macro, beware! We cannot use the do { } while (0)
30 // trick because we use continue in the macro.
31 #define skip_unless_fileid_in(cntvar, lstvar) \
32 while (cntvar && *lstvar < fileid) { \
36 if (!cntvar || *lstvar != fileid) \
40 if (restrict_list) { \
41 skip_unless_fileid_in(restrictcount, restrict_list); \
45 int cPostingList(const uint8_t *restrict list,
47 uint32_t *restrict result,
49 uint32_t *restrict restrict_list) {
53 fileid += uvarint(&list);
55 result[oidx++] = fileid;
60 int cPostingAnd(const uint8_t *restrict list,
62 uint32_t *restrict file_id_list,
64 uint32_t *restrict result,
66 uint32_t *restrict restrict_list) {
70 fileid += uvarint(&list);
72 skip_unless_fileid_in(file_id_count, file_id_list);
73 result[oidx++] = fileid;
78 int cPostingOr(const uint8_t *restrict list,
80 uint32_t *restrict file_id_list,
82 uint32_t *restrict result,
84 uint32_t *restrict restrict_list) {
89 fileid += uvarint(&list);
91 while (fidx < file_id_count && file_id_list[fidx] < fileid)
92 result[oidx++] = file_id_list[fidx++];
93 result[oidx++] = fileid;
94 if (fidx < file_id_count && file_id_list[fidx] == fileid)
97 while (fidx < file_id_count)
98 result[oidx++] = file_id_list[fidx++];
102 int cPostingLast(const uint8_t *restrict list,
105 uint32_t *totalbytes) {
106 const uint8_t *restrict start = list;
108 fileid += uvarint(&list);
110 *totalbytes = (list - start);
117 func myPostingList(data
[]byte, count
int, restrict
[]uint32) []uint32 {
118 result
:= make([]uint32, count
)
122 var restrictptr
*C
.uint32_t
123 if len(restrict
) > 0 {
124 restrictptr
= (*C
.uint32_t
)(&restrict
[0])
126 num
:= C
.cPostingList((*C
.uint8_t
)(&data
[0]),
128 (*C
.uint32_t
)(&result
[0]),
129 C
.int(len(restrict
)),
131 return result
[0:int(num
)]
134 func myPostingAnd(data
[]byte, count
int, list
[]uint32, restrict
[]uint32) []uint32 {
135 // reverse enough space to hold it all, we truncate later
136 result
:= make([]uint32, count
)
140 var listptr
, restrictptr
*C
.uint32_t
141 if len(restrict
) > 0 {
142 restrictptr
= (*C
.uint32_t
)(&restrict
[0])
145 listptr
= (*C
.uint32_t
)(&list
[0])
147 num
:= C
.cPostingAnd((*C
.uint8_t
)(&data
[0]),
151 (*C
.uint32_t
)(&result
[0]),
152 C
.int(len(restrict
)),
154 return result
[0:int(num
)]
157 func myPostingOr(data
[]byte, count
int, list
[]uint32, restrict
[]uint32) []uint32 {
158 if len(list
)+count
== 0 {
161 // reverse enough space to hold it all, we truncate later
162 result
:= make([]uint32, len(list
)+count
)
163 var dataptr
*C
.uint8_t
164 var listptr
, restrictptr
*C
.uint32_t
166 dataptr
= (*C
.uint8_t
)(&data
[0])
168 if len(restrict
) > 0 {
169 restrictptr
= (*C
.uint32_t
)(&restrict
[0])
172 listptr
= (*C
.uint32_t
)(&list
[0])
174 num
:= C
.cPostingOr(dataptr
,
178 (*C
.uint32_t
)(&result
[0]),
179 C
.int(len(restrict
)),
181 return result
[0:int(num
)]
184 func myPostingLast(data
[]byte, count
uint32, fileid
uint32) (int, uint32) {
185 var dataptr
*C
.uint8_t
187 dataptr
= (*C
.uint8_t
)(&data
[0])
189 var totalbytes
uint32
190 last
:= int(C
.cPostingLast(dataptr
,
193 (*C
.uint32_t
)(&totalbytes
)))
194 return last
, totalbytes