Bugfix: construct redirect URLs using net/url
[debiancodesearch.git] / index / myvarint.go
blob2f0a17d7d84f211da47a1aba59e02fdbcb11524a
1 // vim:ts=4:sw=4:noet
2 package index
4 /*
5 #cgo CFLAGS: -std=gnu99 -O3
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdint.h>
10 static __attribute__((hot)) const uint32_t uvarint(const uint8_t *restrict*data) {
11 uint32_t b, c, d;
12 if ((b = *((*data)++)) < 0x80) {
13 return b;
14 } else if ((c = *((*data)++)) < 0x80) {
15 return (uint32_t) (b & 0x7F) |
16 (uint32_t) (c << 7);
17 } else if ((d = *((*data)++)) < 0x80) {
18 return (uint32_t) (b & 0x7F) |
19 (uint32_t)((c & 0x7F) << 7) |
20 (uint32_t) (d << 14);
21 } else {
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) { \
33 cntvar--; \
34 lstvar++; \
35 } \
36 if (!cntvar || *lstvar != fileid) \
37 continue;
39 #define RESTRICT \
40 if (restrict_list) { \
41 skip_unless_fileid_in(restrictcount, restrict_list); \
45 int cPostingList(const uint8_t *restrict list,
46 int count,
47 uint32_t *restrict result,
48 int restrictcount,
49 uint32_t *restrict restrict_list) {
50 int oidx = 0;
51 int fileid = ~0;
52 while (count--) {
53 fileid += uvarint(&list);
54 RESTRICT;
55 result[oidx++] = fileid;
57 return oidx;
60 int cPostingAnd(const uint8_t *restrict list,
61 int count,
62 uint32_t *restrict file_id_list,
63 int file_id_count,
64 uint32_t *restrict result,
65 int restrictcount,
66 uint32_t *restrict restrict_list) {
67 int oidx = 0;
68 int fileid = ~0;
69 while (count--) {
70 fileid += uvarint(&list);
71 RESTRICT;
72 skip_unless_fileid_in(file_id_count, file_id_list);
73 result[oidx++] = fileid;
75 return oidx;
78 int cPostingOr(const uint8_t *restrict list,
79 int count,
80 uint32_t *restrict file_id_list,
81 int file_id_count,
82 uint32_t *restrict result,
83 int restrictcount,
84 uint32_t *restrict restrict_list) {
85 int fidx = 0;
86 int oidx = 0;
87 int fileid = ~0;
88 while (count--) {
89 fileid += uvarint(&list);
90 RESTRICT;
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)
95 fidx++;
97 while (fidx < file_id_count)
98 result[oidx++] = file_id_list[fidx++];
99 return oidx;
102 int cPostingLast(const uint8_t *restrict list,
103 uint32_t count,
104 uint32_t fileid,
105 uint32_t *totalbytes) {
106 const uint8_t *restrict start = list;
107 while (count--) {
108 fileid += uvarint(&list);
110 *totalbytes = (list - start);
111 return fileid;
115 import "C"
117 func myPostingList(data []byte, count int, restrict []uint32) []uint32 {
118 result := make([]uint32, count)
119 if count == 0 {
120 return result
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]),
127 C.int(count),
128 (*C.uint32_t)(&result[0]),
129 C.int(len(restrict)),
130 restrictptr)
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)
137 if count == 0 {
138 return result
140 var listptr, restrictptr *C.uint32_t
141 if len(restrict) > 0 {
142 restrictptr = (*C.uint32_t)(&restrict[0])
144 if len(list) > 0 {
145 listptr = (*C.uint32_t)(&list[0])
147 num := C.cPostingAnd((*C.uint8_t)(&data[0]),
148 C.int(count),
149 listptr,
150 C.int(len(list)),
151 (*C.uint32_t)(&result[0]),
152 C.int(len(restrict)),
153 restrictptr)
154 return result[0:int(num)]
157 func myPostingOr(data []byte, count int, list []uint32, restrict []uint32) []uint32 {
158 if len(list)+count == 0 {
159 return nil
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
165 if count > 0 {
166 dataptr = (*C.uint8_t)(&data[0])
168 if len(restrict) > 0 {
169 restrictptr = (*C.uint32_t)(&restrict[0])
171 if len(list) > 0 {
172 listptr = (*C.uint32_t)(&list[0])
174 num := C.cPostingOr(dataptr,
175 C.int(count),
176 listptr,
177 C.int(len(list)),
178 (*C.uint32_t)(&result[0]),
179 C.int(len(restrict)),
180 restrictptr)
181 return result[0:int(num)]
184 func myPostingLast(data []byte, count uint32, fileid uint32) (int, uint32) {
185 var dataptr *C.uint8_t
186 if count > 0 {
187 dataptr = (*C.uint8_t)(&data[0])
189 var totalbytes uint32
190 last := int(C.cPostingLast(dataptr,
191 C.uint32_t(count),
192 C.uint32_t(fileid),
193 (*C.uint32_t)(&totalbytes)))
194 return last, totalbytes