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 // reverse enough space to hold it all, we truncate later
159 result
:= make([]uint32, len(list
)+count
)
160 var dataptr
*C
.uint8_t
161 var listptr
, restrictptr
*C
.uint32_t
163 dataptr
= (*C
.uint8_t
)(&data
[0])
165 if len(restrict
) > 0 {
166 restrictptr
= (*C
.uint32_t
)(&restrict
[0])
169 listptr
= (*C
.uint32_t
)(&list
[0])
171 num
:= C
.cPostingOr(dataptr
,
175 (*C
.uint32_t
)(&result
[0]),
176 C
.int(len(restrict
)),
178 return result
[0:int(num
)]
181 func myPostingLast(data
[]byte, count
uint32, fileid
uint32) (int, uint32) {
182 var dataptr
*C
.uint8_t
184 dataptr
= (*C
.uint8_t
)(&data
[0])
186 var totalbytes
uint32
187 last
:= int(C
.cPostingLast(dataptr
,
190 (*C
.uint32_t
)(&totalbytes
)))
191 return last
, totalbytes