File: | src/bitops.c |
Warning: | line 316, column 40 The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'uint64_t' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Bit operations. | |||
2 | * | |||
3 | * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> | |||
4 | * All rights reserved. | |||
5 | * | |||
6 | * Redistribution and use in source and binary forms, with or without | |||
7 | * modification, are permitted provided that the following conditions are met: | |||
8 | * | |||
9 | * * Redistributions of source code must retain the above copyright notice, | |||
10 | * this list of conditions and the following disclaimer. | |||
11 | * * Redistributions in binary form must reproduce the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer in the | |||
13 | * documentation and/or other materials provided with the distribution. | |||
14 | * * Neither the name of Redis nor the names of its contributors may be used | |||
15 | * to endorse or promote products derived from this software without | |||
16 | * specific prior written permission. | |||
17 | * | |||
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||
22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
28 | * POSSIBILITY OF SUCH DAMAGE. | |||
29 | */ | |||
30 | ||||
31 | #include "server.h" | |||
32 | ||||
33 | /* ----------------------------------------------------------------------------- | |||
34 | * Helpers and low level bit functions. | |||
35 | * -------------------------------------------------------------------------- */ | |||
36 | ||||
37 | /* Count number of bits set in the binary array pointed by 's' and long | |||
38 | * 'count' bytes. The implementation of this function is required to | |||
39 | * work with an input string length up to 512 MB or more (server.proto_max_bulk_len) */ | |||
40 | size_t redisPopcount(void *s, long count) { | |||
41 | size_t bits = 0; | |||
42 | unsigned char *p = s; | |||
43 | uint32_t *p4; | |||
44 | static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8}; | |||
45 | ||||
46 | /* Count initial bytes not aligned to 32 bit. */ | |||
47 | while((unsigned long)p & 3 && count) { | |||
48 | bits += bitsinbyte[*p++]; | |||
49 | count--; | |||
50 | } | |||
51 | ||||
52 | /* Count bits 28 bytes at a time */ | |||
53 | p4 = (uint32_t*)p; | |||
54 | while(count>=28) { | |||
55 | uint32_t aux1, aux2, aux3, aux4, aux5, aux6, aux7; | |||
56 | ||||
57 | aux1 = *p4++; | |||
58 | aux2 = *p4++; | |||
59 | aux3 = *p4++; | |||
60 | aux4 = *p4++; | |||
61 | aux5 = *p4++; | |||
62 | aux6 = *p4++; | |||
63 | aux7 = *p4++; | |||
64 | count -= 28; | |||
65 | ||||
66 | aux1 = aux1 - ((aux1 >> 1) & 0x55555555); | |||
67 | aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333); | |||
68 | aux2 = aux2 - ((aux2 >> 1) & 0x55555555); | |||
69 | aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333); | |||
70 | aux3 = aux3 - ((aux3 >> 1) & 0x55555555); | |||
71 | aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333); | |||
72 | aux4 = aux4 - ((aux4 >> 1) & 0x55555555); | |||
73 | aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333); | |||
74 | aux5 = aux5 - ((aux5 >> 1) & 0x55555555); | |||
75 | aux5 = (aux5 & 0x33333333) + ((aux5 >> 2) & 0x33333333); | |||
76 | aux6 = aux6 - ((aux6 >> 1) & 0x55555555); | |||
77 | aux6 = (aux6 & 0x33333333) + ((aux6 >> 2) & 0x33333333); | |||
78 | aux7 = aux7 - ((aux7 >> 1) & 0x55555555); | |||
79 | aux7 = (aux7 & 0x33333333) + ((aux7 >> 2) & 0x33333333); | |||
80 | bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) + | |||
81 | ((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) + | |||
82 | ((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) + | |||
83 | ((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) + | |||
84 | ((aux5 + (aux5 >> 4)) & 0x0F0F0F0F) + | |||
85 | ((aux6 + (aux6 >> 4)) & 0x0F0F0F0F) + | |||
86 | ((aux7 + (aux7 >> 4)) & 0x0F0F0F0F))* 0x01010101) >> 24; | |||
87 | } | |||
88 | /* Count the remaining bytes. */ | |||
89 | p = (unsigned char*)p4; | |||
90 | while(count--) bits += bitsinbyte[*p++]; | |||
91 | return bits; | |||
92 | } | |||
93 | ||||
94 | /* Return the position of the first bit set to one (if 'bit' is 1) or | |||
95 | * zero (if 'bit' is 0) in the bitmap starting at 's' and long 'count' bytes. | |||
96 | * | |||
97 | * The function is guaranteed to return a value >= 0 if 'bit' is 0 since if | |||
98 | * no zero bit is found, it returns count*8 assuming the string is zero | |||
99 | * padded on the right. However if 'bit' is 1 it is possible that there is | |||
100 | * not a single set bit in the bitmap. In this special case -1 is returned. */ | |||
101 | long redisBitpos(void *s, unsigned long count, int bit) { | |||
102 | unsigned long *l; | |||
103 | unsigned char *c; | |||
104 | unsigned long skipval, word = 0, one; | |||
105 | long pos = 0; /* Position of bit, to return to the caller. */ | |||
106 | unsigned long j; | |||
107 | int found; | |||
108 | ||||
109 | /* Process whole words first, seeking for first word that is not | |||
110 | * all ones or all zeros respectively if we are looking for zeros | |||
111 | * or ones. This is much faster with large strings having contiguous | |||
112 | * blocks of 1 or 0 bits compared to the vanilla bit per bit processing. | |||
113 | * | |||
114 | * Note that if we start from an address that is not aligned | |||
115 | * to sizeof(unsigned long) we consume it byte by byte until it is | |||
116 | * aligned. */ | |||
117 | ||||
118 | /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */ | |||
119 | skipval = bit ? 0 : UCHAR_MAX(127*2 +1); | |||
120 | c = (unsigned char*) s; | |||
121 | found = 0; | |||
122 | while((unsigned long)c & (sizeof(*l)-1) && count) { | |||
123 | if (*c != skipval) { | |||
124 | found = 1; | |||
125 | break; | |||
126 | } | |||
127 | c++; | |||
128 | count--; | |||
129 | pos += 8; | |||
130 | } | |||
131 | ||||
132 | /* Skip bits with full word step. */ | |||
133 | l = (unsigned long*) c; | |||
134 | if (!found) { | |||
135 | skipval = bit ? 0 : ULONG_MAX(9223372036854775807L *2UL+1UL); | |||
136 | while (count >= sizeof(*l)) { | |||
137 | if (*l != skipval) break; | |||
138 | l++; | |||
139 | count -= sizeof(*l); | |||
140 | pos += sizeof(*l)*8; | |||
141 | } | |||
142 | } | |||
143 | ||||
144 | /* Load bytes into "word" considering the first byte as the most significant | |||
145 | * (we basically consider it as written in big endian, since we consider the | |||
146 | * string as a set of bits from left to right, with the first bit at position | |||
147 | * zero. | |||
148 | * | |||
149 | * Note that the loading is designed to work even when the bytes left | |||
150 | * (count) are less than a full word. We pad it with zero on the right. */ | |||
151 | c = (unsigned char*)l; | |||
152 | for (j = 0; j < sizeof(*l); j++) { | |||
153 | word <<= 8; | |||
154 | if (count) { | |||
155 | word |= *c; | |||
156 | c++; | |||
157 | count--; | |||
158 | } | |||
159 | } | |||
160 | ||||
161 | /* Special case: | |||
162 | * If bits in the string are all zero and we are looking for one, | |||
163 | * return -1 to signal that there is not a single "1" in the whole | |||
164 | * string. This can't happen when we are looking for "0" as we assume | |||
165 | * that the right of the string is zero padded. */ | |||
166 | if (bit == 1 && word == 0) return -1; | |||
167 | ||||
168 | /* Last word left, scan bit by bit. The first thing we need is to | |||
169 | * have a single "1" set in the most significant position in an | |||
170 | * unsigned long. We don't know the size of the long so we use a | |||
171 | * simple trick. */ | |||
172 | one = ULONG_MAX(9223372036854775807L *2UL+1UL); /* All bits set to 1.*/ | |||
173 | one >>= 1; /* All bits set to 1 but the MSB. */ | |||
174 | one = ~one; /* All bits set to 0 but the MSB. */ | |||
175 | ||||
176 | while(one) { | |||
177 | if (((one & word) != 0) == bit) return pos; | |||
178 | pos++; | |||
179 | one >>= 1; | |||
180 | } | |||
181 | ||||
182 | /* If we reached this point, there is a bug in the algorithm, since | |||
183 | * the case of no match is handled as a special case before. */ | |||
184 | serverPanic("End of redisBitpos() reached.")_serverPanic("bitops.c",184,"End of redisBitpos() reached."), __builtin_unreachable(); | |||
185 | return 0; /* Just to avoid warnings. */ | |||
186 | } | |||
187 | ||||
188 | /* The following set.*Bitfield and get.*Bitfield functions implement setting | |||
189 | * and getting arbitrary size (up to 64 bits) signed and unsigned integers | |||
190 | * at arbitrary positions into a bitmap. | |||
191 | * | |||
192 | * The representation considers the bitmap as having the bit number 0 to be | |||
193 | * the most significant bit of the first byte, and so forth, so for example | |||
194 | * setting a 5 bits unsigned integer to value 23 at offset 7 into a bitmap | |||
195 | * previously set to all zeroes, will produce the following representation: | |||
196 | * | |||
197 | * +--------+--------+ | |||
198 | * |00000001|01110000| | |||
199 | * +--------+--------+ | |||
200 | * | |||
201 | * When offsets and integer sizes are aligned to bytes boundaries, this is the | |||
202 | * same as big endian, however when such alignment does not exist, its important | |||
203 | * to also understand how the bits inside a byte are ordered. | |||
204 | * | |||
205 | * Note that this format follows the same convention as SETBIT and related | |||
206 | * commands. | |||
207 | */ | |||
208 | ||||
209 | void setUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, uint64_t value) { | |||
210 | uint64_t byte, bit, byteval, bitval, j; | |||
211 | ||||
212 | for (j = 0; j < bits; j++) { | |||
213 | bitval = (value & ((uint64_t)1<<(bits-1-j))) != 0; | |||
214 | byte = offset >> 3; | |||
215 | bit = 7 - (offset & 0x7); | |||
216 | byteval = p[byte]; | |||
217 | byteval &= ~(1 << bit); | |||
218 | byteval |= bitval << bit; | |||
219 | p[byte] = byteval & 0xff; | |||
220 | offset++; | |||
221 | } | |||
222 | } | |||
223 | ||||
224 | void setSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, int64_t value) { | |||
225 | uint64_t uv = value; /* Casting will add UINT64_MAX + 1 if v is negative. */ | |||
226 | setUnsignedBitfield(p,offset,bits,uv); | |||
227 | } | |||
228 | ||||
229 | uint64_t getUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) { | |||
230 | uint64_t byte, bit, byteval, bitval, j, value = 0; | |||
231 | ||||
232 | for (j = 0; j < bits; j++) { | |||
233 | byte = offset >> 3; | |||
234 | bit = 7 - (offset & 0x7); | |||
235 | byteval = p[byte]; | |||
236 | bitval = (byteval >> bit) & 1; | |||
237 | value = (value<<1) | bitval; | |||
238 | offset++; | |||
239 | } | |||
240 | return value; | |||
241 | } | |||
242 | ||||
243 | int64_t getSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) { | |||
244 | int64_t value; | |||
245 | union {uint64_t u; int64_t i;} conv; | |||
246 | ||||
247 | /* Converting from unsigned to signed is undefined when the value does | |||
248 | * not fit, however here we assume two's complement and the original value | |||
249 | * was obtained from signed -> unsigned conversion, so we'll find the | |||
250 | * most significant bit set if the original value was negative. | |||
251 | * | |||
252 | * Note that two's complement is mandatory for exact-width types | |||
253 | * according to the C99 standard. */ | |||
254 | conv.u = getUnsignedBitfield(p,offset,bits); | |||
255 | value = conv.i; | |||
256 | ||||
257 | /* If the top significant bit is 1, propagate it to all the | |||
258 | * higher bits for two's complement representation of signed | |||
259 | * integers. */ | |||
260 | if (bits < 64 && (value & ((uint64_t)1 << (bits-1)))) | |||
261 | value |= ((uint64_t)-1) << bits; | |||
262 | return value; | |||
263 | } | |||
264 | ||||
265 | /* The following two functions detect overflow of a value in the context | |||
266 | * of storing it as an unsigned or signed integer with the specified | |||
267 | * number of bits. The functions both take the value and a possible increment. | |||
268 | * If no overflow could happen and the value+increment fit inside the limits, | |||
269 | * then zero is returned, otherwise in case of overflow, 1 is returned, | |||
270 | * otherwise in case of underflow, -1 is returned. | |||
271 | * | |||
272 | * When non-zero is returned (overflow or underflow), if not NULL, *limit is | |||
273 | * set to the value the operation should result when an overflow happens, | |||
274 | * depending on the specified overflow semantics: | |||
275 | * | |||
276 | * For BFOVERFLOW_SAT if 1 is returned, *limit it is set maximum value that | |||
277 | * you can store in that integer. when -1 is returned, *limit is set to the | |||
278 | * minimum value that an integer of that size can represent. | |||
279 | * | |||
280 | * For BFOVERFLOW_WRAP *limit is set by performing the operation in order to | |||
281 | * "wrap" around towards zero for unsigned integers, or towards the most | |||
282 | * negative number that is possible to represent for signed integers. */ | |||
283 | ||||
284 | #define BFOVERFLOW_WRAP0 0 | |||
285 | #define BFOVERFLOW_SAT1 1 | |||
286 | #define BFOVERFLOW_FAIL2 2 /* Used by the BITFIELD command implementation. */ | |||
287 | ||||
288 | int checkUnsignedBitfieldOverflow(uint64_t value, int64_t incr, uint64_t bits, int owtype, uint64_t *limit) { | |||
289 | uint64_t max = (bits == 64) ? UINT64_MAX(18446744073709551615UL) : (((uint64_t)1<<bits)-1); | |||
| ||||
290 | int64_t maxincr = max-value; | |||
291 | int64_t minincr = -value; | |||
292 | ||||
293 | if (value
| |||
294 | if (limit) { | |||
295 | if (owtype == BFOVERFLOW_WRAP0) { | |||
296 | goto handle_wrap; | |||
297 | } else if (owtype == BFOVERFLOW_SAT1) { | |||
298 | *limit = max; | |||
299 | } | |||
300 | } | |||
301 | return 1; | |||
302 | } else if (incr < 0 && incr < minincr) { | |||
303 | if (limit) { | |||
304 | if (owtype == BFOVERFLOW_WRAP0) { | |||
305 | goto handle_wrap; | |||
306 | } else if (owtype == BFOVERFLOW_SAT1) { | |||
307 | *limit = 0; | |||
308 | } | |||
309 | } | |||
310 | return -1; | |||
311 | } | |||
312 | return 0; | |||
313 | ||||
314 | handle_wrap: | |||
315 | { | |||
316 | uint64_t mask = ((uint64_t)-1) << bits; | |||
| ||||
317 | uint64_t res = value+incr; | |||
318 | ||||
319 | res &= ~mask; | |||
320 | *limit = res; | |||
321 | } | |||
322 | return 1; | |||
323 | } | |||
324 | ||||
325 | int checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int owtype, int64_t *limit) { | |||
326 | int64_t max = (bits == 64) ? INT64_MAX(9223372036854775807L) : (((int64_t)1<<(bits-1))-1); | |||
327 | int64_t min = (-max)-1; | |||
328 | ||||
329 | /* Note that maxincr and minincr could overflow, but we use the values | |||
330 | * only after checking 'value' range, so when we use it no overflow | |||
331 | * happens. */ | |||
332 | int64_t maxincr = max-value; | |||
333 | int64_t minincr = min-value; | |||
334 | ||||
335 | if (value > max || (bits != 64 && incr > maxincr) || (value >= 0 && incr > 0 && incr > maxincr)) | |||
336 | { | |||
337 | if (limit) { | |||
338 | if (owtype == BFOVERFLOW_WRAP0) { | |||
339 | goto handle_wrap; | |||
340 | } else if (owtype == BFOVERFLOW_SAT1) { | |||
341 | *limit = max; | |||
342 | } | |||
343 | } | |||
344 | return 1; | |||
345 | } else if (value < min || (bits != 64 && incr < minincr) || (value < 0 && incr < 0 && incr < minincr)) { | |||
346 | if (limit) { | |||
347 | if (owtype == BFOVERFLOW_WRAP0) { | |||
348 | goto handle_wrap; | |||
349 | } else if (owtype == BFOVERFLOW_SAT1) { | |||
350 | *limit = min; | |||
351 | } | |||
352 | } | |||
353 | return -1; | |||
354 | } | |||
355 | return 0; | |||
356 | ||||
357 | handle_wrap: | |||
358 | { | |||
359 | uint64_t msb = (uint64_t)1 << (bits-1); | |||
360 | uint64_t a = value, b = incr, c; | |||
361 | c = a+b; /* Perform addition as unsigned so that's defined. */ | |||
362 | ||||
363 | /* If the sign bit is set, propagate to all the higher order | |||
364 | * bits, to cap the negative value. If it's clear, mask to | |||
365 | * the positive integer limit. */ | |||
366 | if (bits < 64) { | |||
367 | uint64_t mask = ((uint64_t)-1) << bits; | |||
368 | if (c & msb) { | |||
369 | c |= mask; | |||
370 | } else { | |||
371 | c &= ~mask; | |||
372 | } | |||
373 | } | |||
374 | *limit = c; | |||
375 | } | |||
376 | return 1; | |||
377 | } | |||
378 | ||||
379 | /* Debugging function. Just show bits in the specified bitmap. Not used | |||
380 | * but here for not having to rewrite it when debugging is needed. */ | |||
381 | void printBits(unsigned char *p, unsigned long count) { | |||
382 | unsigned long j, i, byte; | |||
383 | ||||
384 | for (j = 0; j < count; j++) { | |||
385 | byte = p[j]; | |||
386 | for (i = 0x80; i > 0; i /= 2) | |||
387 | printf("%c", (byte & i) ? '1' : '0'); | |||
388 | printf("|"); | |||
389 | } | |||
390 | printf("\n"); | |||
391 | } | |||
392 | ||||
393 | /* ----------------------------------------------------------------------------- | |||
394 | * Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP. | |||
395 | * -------------------------------------------------------------------------- */ | |||
396 | ||||
397 | #define BITOP_AND0 0 | |||
398 | #define BITOP_OR1 1 | |||
399 | #define BITOP_XOR2 2 | |||
400 | #define BITOP_NOT3 3 | |||
401 | ||||
402 | #define BITFIELDOP_GET0 0 | |||
403 | #define BITFIELDOP_SET1 1 | |||
404 | #define BITFIELDOP_INCRBY2 2 | |||
405 | ||||
406 | /* This helper function used by GETBIT / SETBIT parses the bit offset argument | |||
407 | * making sure an error is returned if it is negative or if it overflows | |||
408 | * Redis 512 MB limit for the string value or more (server.proto_max_bulk_len). | |||
409 | * | |||
410 | * If the 'hash' argument is true, and 'bits is positive, then the command | |||
411 | * will also parse bit offsets prefixed by "#". In such a case the offset | |||
412 | * is multiplied by 'bits'. This is useful for the BITFIELD command. */ | |||
413 | int getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int bits) { | |||
414 | long long loffset; | |||
415 | char *err = "bit offset is not an integer or out of range"; | |||
416 | char *p = o->ptr; | |||
417 | size_t plen = sdslen(p); | |||
418 | int usehash = 0; | |||
419 | ||||
420 | /* Handle #<offset> form. */ | |||
421 | if (p[0] == '#' && hash && bits > 0) usehash = 1; | |||
422 | ||||
423 | if (string2ll(p+usehash,plen-usehash,&loffset) == 0) { | |||
424 | addReplyError(c,err); | |||
425 | return C_ERR-1; | |||
426 | } | |||
427 | ||||
428 | /* Adjust the offset by 'bits' for #<offset> form. */ | |||
429 | if (usehash) loffset *= bits; | |||
430 | ||||
431 | /* Limit offset to server.proto_max_bulk_len (512MB in bytes by default) */ | |||
432 | if ((loffset < 0) || (loffset >> 3) >= server.proto_max_bulk_len) | |||
433 | { | |||
434 | addReplyError(c,err); | |||
435 | return C_ERR-1; | |||
436 | } | |||
437 | ||||
438 | *offset = (size_t)loffset; | |||
439 | return C_OK0; | |||
440 | } | |||
441 | ||||
442 | /* This helper function for BITFIELD parses a bitfield type in the form | |||
443 | * <sign><bits> where sign is 'u' or 'i' for unsigned and signed, and | |||
444 | * the bits is a value between 1 and 64. However 64 bits unsigned integers | |||
445 | * are reported as an error because of current limitations of Redis protocol | |||
446 | * to return unsigned integer values greater than INT64_MAX. | |||
447 | * | |||
448 | * On error C_ERR is returned and an error is sent to the client. */ | |||
449 | int getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) { | |||
450 | char *p = o->ptr; | |||
451 | char *err = "Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is."; | |||
452 | long long llbits; | |||
453 | ||||
454 | if (p[0] == 'i') { | |||
455 | *sign = 1; | |||
456 | } else if (p[0] == 'u') { | |||
457 | *sign = 0; | |||
458 | } else { | |||
459 | addReplyError(c,err); | |||
460 | return C_ERR-1; | |||
461 | } | |||
462 | ||||
463 | if ((string2ll(p+1,strlen(p+1),&llbits)) == 0 || | |||
464 | llbits < 1 || | |||
465 | (*sign == 1 && llbits > 64) || | |||
466 | (*sign == 0 && llbits > 63)) | |||
467 | { | |||
468 | addReplyError(c,err); | |||
469 | return C_ERR-1; | |||
470 | } | |||
471 | *bits = llbits; | |||
472 | return C_OK0; | |||
473 | } | |||
474 | ||||
475 | /* This is an helper function for commands implementations that need to write | |||
476 | * bits to a string object. The command creates or pad with zeroes the string | |||
477 | * so that the 'maxbit' bit can be addressed. The object is finally | |||
478 | * returned. Otherwise if the key holds a wrong type NULL is returned and | |||
479 | * an error is sent to the client. */ | |||
480 | robj *lookupStringForBitCommand(client *c, size_t maxbit) { | |||
481 | size_t byte = maxbit >> 3; | |||
482 | robj *o = lookupKeyWrite(c->db,c->argv[1]); | |||
483 | if (checkType(c,o,OBJ_STRING0)) return NULL((void*)0); | |||
484 | ||||
485 | if (o == NULL((void*)0)) { | |||
486 | o = createObject(OBJ_STRING0,sdsnewlen(NULL((void*)0), byte+1)); | |||
487 | dbAdd(c->db,c->argv[1],o); | |||
488 | } else { | |||
489 | o = dbUnshareStringValue(c->db,c->argv[1],o); | |||
490 | o->ptr = sdsgrowzero(o->ptr,byte+1); | |||
491 | } | |||
492 | return o; | |||
493 | } | |||
494 | ||||
495 | /* Return a pointer to the string object content, and stores its length | |||
496 | * in 'len'. The user is required to pass (likely stack allocated) buffer | |||
497 | * 'llbuf' of at least LONG_STR_SIZE bytes. Such a buffer is used in the case | |||
498 | * the object is integer encoded in order to provide the representation | |||
499 | * without using heap allocation. | |||
500 | * | |||
501 | * The function returns the pointer to the object array of bytes representing | |||
502 | * the string it contains, that may be a pointer to 'llbuf' or to the | |||
503 | * internal object representation. As a side effect 'len' is filled with | |||
504 | * the length of such buffer. | |||
505 | * | |||
506 | * If the source object is NULL the function is guaranteed to return NULL | |||
507 | * and set 'len' to 0. */ | |||
508 | unsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) { | |||
509 | serverAssert(o->type == OBJ_STRING)((o->type == 0)?(void)0 : (_serverAssert("o->type == OBJ_STRING" ,"bitops.c",509),__builtin_unreachable())); | |||
510 | unsigned char *p = NULL((void*)0); | |||
511 | ||||
512 | /* Set the 'p' pointer to the string, that can be just a stack allocated | |||
513 | * array if our string was integer encoded. */ | |||
514 | if (o && o->encoding == OBJ_ENCODING_INT1) { | |||
515 | p = (unsigned char*) llbuf; | |||
516 | if (len) *len = ll2string(llbuf,LONG_STR_SIZE21,(long)o->ptr); | |||
517 | } else if (o) { | |||
518 | p = (unsigned char*) o->ptr; | |||
519 | if (len) *len = sdslen(o->ptr); | |||
520 | } else { | |||
521 | if (len) *len = 0; | |||
522 | } | |||
523 | return p; | |||
524 | } | |||
525 | ||||
526 | /* SETBIT key offset bitvalue */ | |||
527 | void setbitCommand(client *c) { | |||
528 | robj *o; | |||
529 | char *err = "bit is not an integer or out of range"; | |||
530 | size_t bitoffset; | |||
531 | ssize_t byte, bit; | |||
532 | int byteval, bitval; | |||
533 | long on; | |||
534 | ||||
535 | if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK0) | |||
536 | return; | |||
537 | ||||
538 | if (getLongFromObjectOrReply(c,c->argv[3],&on,err) != C_OK0) | |||
539 | return; | |||
540 | ||||
541 | /* Bits can only be set or cleared... */ | |||
542 | if (on & ~1) { | |||
543 | addReplyError(c,err); | |||
544 | return; | |||
545 | } | |||
546 | ||||
547 | if ((o = lookupStringForBitCommand(c,bitoffset)) == NULL((void*)0)) return; | |||
548 | ||||
549 | /* Get current values */ | |||
550 | byte = bitoffset >> 3; | |||
551 | byteval = ((uint8_t*)o->ptr)[byte]; | |||
552 | bit = 7 - (bitoffset & 0x7); | |||
553 | bitval = byteval & (1 << bit); | |||
554 | ||||
555 | /* Update byte with new bit value and return original value */ | |||
556 | byteval &= ~(1 << bit); | |||
557 | byteval |= ((on & 0x1) << bit); | |||
558 | ((uint8_t*)o->ptr)[byte] = byteval; | |||
559 | signalModifiedKey(c,c->db,c->argv[1]); | |||
560 | notifyKeyspaceEvent(NOTIFY_STRING(1<<3),"setbit",c->argv[1],c->db->id); | |||
561 | server.dirty++; | |||
562 | addReply(c, bitval ? shared.cone : shared.czero); | |||
563 | } | |||
564 | ||||
565 | /* GETBIT key offset */ | |||
566 | void getbitCommand(client *c) { | |||
567 | robj *o; | |||
568 | char llbuf[32]; | |||
569 | size_t bitoffset; | |||
570 | size_t byte, bit; | |||
571 | size_t bitval = 0; | |||
572 | ||||
573 | if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK0) | |||
574 | return; | |||
575 | ||||
576 | if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL((void*)0) || | |||
577 | checkType(c,o,OBJ_STRING0)) return; | |||
578 | ||||
579 | byte = bitoffset >> 3; | |||
580 | bit = 7 - (bitoffset & 0x7); | |||
581 | if (sdsEncodedObject(o)(o->encoding == 0 || o->encoding == 8)) { | |||
582 | if (byte < sdslen(o->ptr)) | |||
583 | bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit); | |||
584 | } else { | |||
585 | if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr)) | |||
586 | bitval = llbuf[byte] & (1 << bit); | |||
587 | } | |||
588 | ||||
589 | addReply(c, bitval ? shared.cone : shared.czero); | |||
590 | } | |||
591 | ||||
592 | /* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */ | |||
593 | void bitopCommand(client *c) { | |||
594 | char *opname = c->argv[1]->ptr; | |||
595 | robj *o, *targetkey = c->argv[2]; | |||
596 | unsigned long op, j, numkeys; | |||
597 | robj **objects; /* Array of source objects. */ | |||
598 | unsigned char **src; /* Array of source strings pointers. */ | |||
599 | unsigned long *len, maxlen = 0; /* Array of length of src strings, | |||
600 | and max len. */ | |||
601 | unsigned long minlen = 0; /* Min len among the input keys. */ | |||
602 | unsigned char *res = NULL((void*)0); /* Resulting string. */ | |||
603 | ||||
604 | /* Parse the operation name. */ | |||
605 | if ((opname[0] == 'a' || opname[0] == 'A') && !strcasecmp(opname,"and")) | |||
606 | op = BITOP_AND0; | |||
607 | else if((opname[0] == 'o' || opname[0] == 'O') && !strcasecmp(opname,"or")) | |||
608 | op = BITOP_OR1; | |||
609 | else if((opname[0] == 'x' || opname[0] == 'X') && !strcasecmp(opname,"xor")) | |||
610 | op = BITOP_XOR2; | |||
611 | else if((opname[0] == 'n' || opname[0] == 'N') && !strcasecmp(opname,"not")) | |||
612 | op = BITOP_NOT3; | |||
613 | else { | |||
614 | addReplyErrorObject(c,shared.syntaxerr); | |||
615 | return; | |||
616 | } | |||
617 | ||||
618 | /* Sanity check: NOT accepts only a single key argument. */ | |||
619 | if (op == BITOP_NOT3 && c->argc != 4) { | |||
620 | addReplyError(c,"BITOP NOT must be called with a single source key."); | |||
621 | return; | |||
622 | } | |||
623 | ||||
624 | /* Lookup keys, and store pointers to the string objects into an array. */ | |||
625 | numkeys = c->argc - 3; | |||
626 | src = zmalloc(sizeof(unsigned char*) * numkeys); | |||
627 | len = zmalloc(sizeof(long) * numkeys); | |||
628 | objects = zmalloc(sizeof(robj*) * numkeys); | |||
629 | for (j = 0; j < numkeys; j++) { | |||
630 | o = lookupKeyRead(c->db,c->argv[j+3]); | |||
631 | /* Handle non-existing keys as empty strings. */ | |||
632 | if (o == NULL((void*)0)) { | |||
633 | objects[j] = NULL((void*)0); | |||
634 | src[j] = NULL((void*)0); | |||
635 | len[j] = 0; | |||
636 | minlen = 0; | |||
637 | continue; | |||
638 | } | |||
639 | /* Return an error if one of the keys is not a string. */ | |||
640 | if (checkType(c,o,OBJ_STRING0)) { | |||
641 | unsigned long i; | |||
642 | for (i = 0; i < j; i++) { | |||
643 | if (objects[i]) | |||
644 | decrRefCount(objects[i]); | |||
645 | } | |||
646 | zfree(src); | |||
647 | zfree(len); | |||
648 | zfree(objects); | |||
649 | return; | |||
650 | } | |||
651 | objects[j] = getDecodedObject(o); | |||
652 | src[j] = objects[j]->ptr; | |||
653 | len[j] = sdslen(objects[j]->ptr); | |||
654 | if (len[j] > maxlen) maxlen = len[j]; | |||
655 | if (j == 0 || len[j] < minlen) minlen = len[j]; | |||
656 | } | |||
657 | ||||
658 | /* Compute the bit operation, if at least one string is not empty. */ | |||
659 | if (maxlen) { | |||
660 | res = (unsigned char*) sdsnewlen(NULL((void*)0),maxlen); | |||
661 | unsigned char output, byte; | |||
662 | unsigned long i; | |||
663 | ||||
664 | /* Fast path: as far as we have data for all the input bitmaps we | |||
665 | * can take a fast path that performs much better than the | |||
666 | * vanilla algorithm. On ARM we skip the fast path since it will | |||
667 | * result in GCC compiling the code using multiple-words load/store | |||
668 | * operations that are not supported even in ARM >= v6. */ | |||
669 | j = 0; | |||
670 | #ifndef USE_ALIGNED_ACCESS | |||
671 | if (minlen >= sizeof(unsigned long)*4 && numkeys <= 16) { | |||
672 | unsigned long *lp[16]; | |||
673 | unsigned long *lres = (unsigned long*) res; | |||
674 | ||||
675 | /* Note: sds pointer is always aligned to 8 byte boundary. */ | |||
676 | memcpy(lp,src,sizeof(unsigned long*)*numkeys); | |||
677 | memcpy(res,src[0],minlen); | |||
678 | ||||
679 | /* Different branches per different operations for speed (sorry). */ | |||
680 | if (op == BITOP_AND0) { | |||
681 | while(minlen >= sizeof(unsigned long)*4) { | |||
682 | for (i = 1; i < numkeys; i++) { | |||
683 | lres[0] &= lp[i][0]; | |||
684 | lres[1] &= lp[i][1]; | |||
685 | lres[2] &= lp[i][2]; | |||
686 | lres[3] &= lp[i][3]; | |||
687 | lp[i]+=4; | |||
688 | } | |||
689 | lres+=4; | |||
690 | j += sizeof(unsigned long)*4; | |||
691 | minlen -= sizeof(unsigned long)*4; | |||
692 | } | |||
693 | } else if (op == BITOP_OR1) { | |||
694 | while(minlen >= sizeof(unsigned long)*4) { | |||
695 | for (i = 1; i < numkeys; i++) { | |||
696 | lres[0] |= lp[i][0]; | |||
697 | lres[1] |= lp[i][1]; | |||
698 | lres[2] |= lp[i][2]; | |||
699 | lres[3] |= lp[i][3]; | |||
700 | lp[i]+=4; | |||
701 | } | |||
702 | lres+=4; | |||
703 | j += sizeof(unsigned long)*4; | |||
704 | minlen -= sizeof(unsigned long)*4; | |||
705 | } | |||
706 | } else if (op == BITOP_XOR2) { | |||
707 | while(minlen >= sizeof(unsigned long)*4) { | |||
708 | for (i = 1; i < numkeys; i++) { | |||
709 | lres[0] ^= lp[i][0]; | |||
710 | lres[1] ^= lp[i][1]; | |||
711 | lres[2] ^= lp[i][2]; | |||
712 | lres[3] ^= lp[i][3]; | |||
713 | lp[i]+=4; | |||
714 | } | |||
715 | lres+=4; | |||
716 | j += sizeof(unsigned long)*4; | |||
717 | minlen -= sizeof(unsigned long)*4; | |||
718 | } | |||
719 | } else if (op == BITOP_NOT3) { | |||
720 | while(minlen >= sizeof(unsigned long)*4) { | |||
721 | lres[0] = ~lres[0]; | |||
722 | lres[1] = ~lres[1]; | |||
723 | lres[2] = ~lres[2]; | |||
724 | lres[3] = ~lres[3]; | |||
725 | lres+=4; | |||
726 | j += sizeof(unsigned long)*4; | |||
727 | minlen -= sizeof(unsigned long)*4; | |||
728 | } | |||
729 | } | |||
730 | } | |||
731 | #endif | |||
732 | ||||
733 | /* j is set to the next byte to process by the previous loop. */ | |||
734 | for (; j < maxlen; j++) { | |||
735 | output = (len[0] <= j) ? 0 : src[0][j]; | |||
736 | if (op == BITOP_NOT3) output = ~output; | |||
737 | for (i = 1; i < numkeys; i++) { | |||
738 | int skip = 0; | |||
739 | byte = (len[i] <= j) ? 0 : src[i][j]; | |||
740 | switch(op) { | |||
741 | case BITOP_AND0: | |||
742 | output &= byte; | |||
743 | skip = (output == 0); | |||
744 | break; | |||
745 | case BITOP_OR1: | |||
746 | output |= byte; | |||
747 | skip = (output == 0xff); | |||
748 | break; | |||
749 | case BITOP_XOR2: output ^= byte; break; | |||
750 | } | |||
751 | ||||
752 | if (skip) { | |||
753 | break; | |||
754 | } | |||
755 | } | |||
756 | res[j] = output; | |||
757 | } | |||
758 | } | |||
759 | for (j = 0; j < numkeys; j++) { | |||
760 | if (objects[j]) | |||
761 | decrRefCount(objects[j]); | |||
762 | } | |||
763 | zfree(src); | |||
764 | zfree(len); | |||
765 | zfree(objects); | |||
766 | ||||
767 | /* Store the computed value into the target key */ | |||
768 | if (maxlen) { | |||
769 | o = createObject(OBJ_STRING0,res); | |||
770 | setKey(c,c->db,targetkey,o); | |||
771 | notifyKeyspaceEvent(NOTIFY_STRING(1<<3),"set",targetkey,c->db->id); | |||
772 | decrRefCount(o); | |||
773 | server.dirty++; | |||
774 | } else if (dbDelete(c->db,targetkey)) { | |||
775 | signalModifiedKey(c,c->db,targetkey); | |||
776 | notifyKeyspaceEvent(NOTIFY_GENERIC(1<<2),"del",targetkey,c->db->id); | |||
777 | server.dirty++; | |||
778 | } | |||
779 | addReplyLongLong(c,maxlen); /* Return the output string length in bytes. */ | |||
780 | } | |||
781 | ||||
782 | /* BITCOUNT key [start end] */ | |||
783 | void bitcountCommand(client *c) { | |||
784 | robj *o; | |||
785 | long start, end, strlen; | |||
786 | unsigned char *p; | |||
787 | char llbuf[LONG_STR_SIZE21]; | |||
788 | ||||
789 | /* Lookup, check for type, and return 0 for non existing keys. */ | |||
790 | if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL((void*)0) || | |||
791 | checkType(c,o,OBJ_STRING0)) return; | |||
792 | p = getObjectReadOnlyString(o,&strlen,llbuf); | |||
793 | ||||
794 | /* Parse start/end range if any. */ | |||
795 | if (c->argc == 4) { | |||
796 | if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL((void*)0)) != C_OK0) | |||
797 | return; | |||
798 | if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL((void*)0)) != C_OK0) | |||
799 | return; | |||
800 | /* Convert negative indexes */ | |||
801 | if (start < 0 && end < 0 && start > end) { | |||
802 | addReply(c,shared.czero); | |||
803 | return; | |||
804 | } | |||
805 | if (start < 0) start = strlen+start; | |||
806 | if (end < 0) end = strlen+end; | |||
807 | if (start < 0) start = 0; | |||
808 | if (end < 0) end = 0; | |||
809 | if (end >= strlen) end = strlen-1; | |||
810 | } else if (c->argc == 2) { | |||
811 | /* The whole string. */ | |||
812 | start = 0; | |||
813 | end = strlen-1; | |||
814 | } else { | |||
815 | /* Syntax error. */ | |||
816 | addReplyErrorObject(c,shared.syntaxerr); | |||
817 | return; | |||
818 | } | |||
819 | ||||
820 | /* Precondition: end >= 0 && end < strlen, so the only condition where | |||
821 | * zero can be returned is: start > end. */ | |||
822 | if (start > end) { | |||
823 | addReply(c,shared.czero); | |||
824 | } else { | |||
825 | long bytes = end-start+1; | |||
826 | ||||
827 | addReplyLongLong(c,redisPopcount(p+start,bytes)); | |||
828 | } | |||
829 | } | |||
830 | ||||
831 | /* BITPOS key bit [start [end]] */ | |||
832 | void bitposCommand(client *c) { | |||
833 | robj *o; | |||
834 | long bit, start, end, strlen; | |||
835 | unsigned char *p; | |||
836 | char llbuf[LONG_STR_SIZE21]; | |||
837 | int end_given = 0; | |||
838 | ||||
839 | /* Parse the bit argument to understand what we are looking for, set | |||
840 | * or clear bits. */ | |||
841 | if (getLongFromObjectOrReply(c,c->argv[2],&bit,NULL((void*)0)) != C_OK0) | |||
842 | return; | |||
843 | if (bit != 0 && bit != 1) { | |||
844 | addReplyError(c, "The bit argument must be 1 or 0."); | |||
845 | return; | |||
846 | } | |||
847 | ||||
848 | /* If the key does not exist, from our point of view it is an infinite | |||
849 | * array of 0 bits. If the user is looking for the fist clear bit return 0, | |||
850 | * If the user is looking for the first set bit, return -1. */ | |||
851 | if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL((void*)0)) { | |||
852 | addReplyLongLong(c, bit ? -1 : 0); | |||
853 | return; | |||
854 | } | |||
855 | if (checkType(c,o,OBJ_STRING0)) return; | |||
856 | p = getObjectReadOnlyString(o,&strlen,llbuf); | |||
857 | ||||
858 | /* Parse start/end range if any. */ | |||
859 | if (c->argc == 4 || c->argc == 5) { | |||
860 | if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL((void*)0)) != C_OK0) | |||
861 | return; | |||
862 | if (c->argc == 5) { | |||
863 | if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL((void*)0)) != C_OK0) | |||
864 | return; | |||
865 | end_given = 1; | |||
866 | } else { | |||
867 | end = strlen-1; | |||
868 | } | |||
869 | /* Convert negative indexes */ | |||
870 | if (start < 0) start = strlen+start; | |||
871 | if (end < 0) end = strlen+end; | |||
872 | if (start < 0) start = 0; | |||
873 | if (end < 0) end = 0; | |||
874 | if (end >= strlen) end = strlen-1; | |||
875 | } else if (c->argc == 3) { | |||
876 | /* The whole string. */ | |||
877 | start = 0; | |||
878 | end = strlen-1; | |||
879 | } else { | |||
880 | /* Syntax error. */ | |||
881 | addReplyErrorObject(c,shared.syntaxerr); | |||
882 | return; | |||
883 | } | |||
884 | ||||
885 | /* For empty ranges (start > end) we return -1 as an empty range does | |||
886 | * not contain a 0 nor a 1. */ | |||
887 | if (start > end) { | |||
888 | addReplyLongLong(c, -1); | |||
889 | } else { | |||
890 | long bytes = end-start+1; | |||
891 | long pos = redisBitpos(p+start,bytes,bit); | |||
892 | ||||
893 | /* If we are looking for clear bits, and the user specified an exact | |||
894 | * range with start-end, we can't consider the right of the range as | |||
895 | * zero padded (as we do when no explicit end is given). | |||
896 | * | |||
897 | * So if redisBitpos() returns the first bit outside the range, | |||
898 | * we return -1 to the caller, to mean, in the specified range there | |||
899 | * is not a single "0" bit. */ | |||
900 | if (end_given && bit == 0 && pos == bytes*8) { | |||
901 | addReplyLongLong(c,-1); | |||
902 | return; | |||
903 | } | |||
904 | if (pos != -1) pos += start*8; /* Adjust for the bytes we skipped. */ | |||
905 | addReplyLongLong(c,pos); | |||
906 | } | |||
907 | } | |||
908 | ||||
909 | /* BITFIELD key subcommmand-1 arg ... subcommand-2 arg ... subcommand-N ... | |||
910 | * | |||
911 | * Supported subcommands: | |||
912 | * | |||
913 | * GET <type> <offset> | |||
914 | * SET <type> <offset> <value> | |||
915 | * INCRBY <type> <offset> <increment> | |||
916 | * OVERFLOW [WRAP|SAT|FAIL] | |||
917 | */ | |||
918 | ||||
919 | #define BITFIELD_FLAG_NONE0 0 | |||
920 | #define BITFIELD_FLAG_READONLY(1<<0) (1<<0) | |||
921 | ||||
922 | struct bitfieldOp { | |||
923 | uint64_t offset; /* Bitfield offset. */ | |||
924 | int64_t i64; /* Increment amount (INCRBY) or SET value */ | |||
925 | int opcode; /* Operation id. */ | |||
926 | int owtype; /* Overflow type to use. */ | |||
927 | int bits; /* Integer bitfield bits width. */ | |||
928 | int sign; /* True if signed, otherwise unsigned op. */ | |||
929 | }; | |||
930 | ||||
931 | /* This implements both the BITFIELD command and the BITFIELD_RO command | |||
932 | * when flags is set to BITFIELD_FLAG_READONLY: in this case only the | |||
933 | * GET subcommand is allowed, other subcommands will return an error. */ | |||
934 | void bitfieldGeneric(client *c, int flags) { | |||
935 | robj *o; | |||
936 | size_t bitoffset; | |||
937 | int j, numops = 0, changes = 0; | |||
938 | struct bitfieldOp *ops = NULL((void*)0); /* Array of ops to execute at end. */ | |||
939 | int owtype = BFOVERFLOW_WRAP0; /* Overflow type. */ | |||
940 | int readonly = 1; | |||
941 | size_t highest_write_offset = 0; | |||
942 | ||||
943 | for (j = 2; j < c->argc; j++) { | |||
944 | int remargs = c->argc-j-1; /* Remaining args other than current. */ | |||
945 | char *subcmd = c->argv[j]->ptr; /* Current command name. */ | |||
946 | int opcode; /* Current operation code. */ | |||
947 | long long i64 = 0; /* Signed SET value. */ | |||
948 | int sign = 0; /* Signed or unsigned type? */ | |||
949 | int bits = 0; /* Bitfield width in bits. */ | |||
950 | ||||
951 | if (!strcasecmp(subcmd,"get") && remargs >= 2) | |||
952 | opcode = BITFIELDOP_GET0; | |||
953 | else if (!strcasecmp(subcmd,"set") && remargs >= 3) | |||
954 | opcode = BITFIELDOP_SET1; | |||
955 | else if (!strcasecmp(subcmd,"incrby") && remargs >= 3) | |||
956 | opcode = BITFIELDOP_INCRBY2; | |||
957 | else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) { | |||
958 | char *owtypename = c->argv[j+1]->ptr; | |||
959 | j++; | |||
960 | if (!strcasecmp(owtypename,"wrap")) | |||
961 | owtype = BFOVERFLOW_WRAP0; | |||
962 | else if (!strcasecmp(owtypename,"sat")) | |||
963 | owtype = BFOVERFLOW_SAT1; | |||
964 | else if (!strcasecmp(owtypename,"fail")) | |||
965 | owtype = BFOVERFLOW_FAIL2; | |||
966 | else { | |||
967 | addReplyError(c,"Invalid OVERFLOW type specified"); | |||
968 | zfree(ops); | |||
969 | return; | |||
970 | } | |||
971 | continue; | |||
972 | } else { | |||
973 | addReplyErrorObject(c,shared.syntaxerr); | |||
974 | zfree(ops); | |||
975 | return; | |||
976 | } | |||
977 | ||||
978 | /* Get the type and offset arguments, common to all the ops. */ | |||
979 | if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK0) { | |||
980 | zfree(ops); | |||
981 | return; | |||
982 | } | |||
983 | ||||
984 | if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK0){ | |||
985 | zfree(ops); | |||
986 | return; | |||
987 | } | |||
988 | ||||
989 | if (opcode != BITFIELDOP_GET0) { | |||
990 | readonly = 0; | |||
991 | if (highest_write_offset < bitoffset + bits - 1) | |||
992 | highest_write_offset = bitoffset + bits - 1; | |||
993 | /* INCRBY and SET require another argument. */ | |||
994 | if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL((void*)0)) != C_OK0){ | |||
995 | zfree(ops); | |||
996 | return; | |||
997 | } | |||
998 | } | |||
999 | ||||
1000 | /* Populate the array of operations we'll process. */ | |||
1001 | ops = zrealloc(ops,sizeof(*ops)*(numops+1)); | |||
1002 | ops[numops].offset = bitoffset; | |||
1003 | ops[numops].i64 = i64; | |||
1004 | ops[numops].opcode = opcode; | |||
1005 | ops[numops].owtype = owtype; | |||
1006 | ops[numops].bits = bits; | |||
1007 | ops[numops].sign = sign; | |||
1008 | numops++; | |||
1009 | ||||
1010 | j += 3 - (opcode == BITFIELDOP_GET0); | |||
1011 | } | |||
1012 | ||||
1013 | if (readonly) { | |||
1014 | /* Lookup for read is ok if key doesn't exit, but errors | |||
1015 | * if it's not a string. */ | |||
1016 | o = lookupKeyRead(c->db,c->argv[1]); | |||
1017 | if (o != NULL((void*)0) && checkType(c,o,OBJ_STRING0)) { | |||
1018 | zfree(ops); | |||
1019 | return; | |||
1020 | } | |||
1021 | } else { | |||
1022 | if (flags & BITFIELD_FLAG_READONLY(1<<0)) { | |||
1023 | zfree(ops); | |||
1024 | addReplyError(c, "BITFIELD_RO only supports the GET subcommand"); | |||
1025 | return; | |||
1026 | } | |||
1027 | ||||
1028 | /* Lookup by making room up to the farest bit reached by | |||
1029 | * this operation. */ | |||
1030 | if ((o = lookupStringForBitCommand(c, | |||
1031 | highest_write_offset)) == NULL((void*)0)) { | |||
1032 | zfree(ops); | |||
1033 | return; | |||
1034 | } | |||
1035 | } | |||
1036 | ||||
1037 | addReplyArrayLen(c,numops); | |||
1038 | ||||
1039 | /* Actually process the operations. */ | |||
1040 | for (j = 0; j < numops; j++) { | |||
1041 | struct bitfieldOp *thisop = ops+j; | |||
1042 | ||||
1043 | /* Execute the operation. */ | |||
1044 | if (thisop->opcode == BITFIELDOP_SET1 || | |||
1045 | thisop->opcode == BITFIELDOP_INCRBY2) | |||
1046 | { | |||
1047 | /* SET and INCRBY: We handle both with the same code path | |||
1048 | * for simplicity. SET return value is the previous value so | |||
1049 | * we need fetch & store as well. */ | |||
1050 | ||||
1051 | /* We need two different but very similar code paths for signed | |||
1052 | * and unsigned operations, since the set of functions to get/set | |||
1053 | * the integers and the used variables types are different. */ | |||
1054 | if (thisop->sign) { | |||
1055 | int64_t oldval, newval, wrapped, retval; | |||
1056 | int overflow; | |||
1057 | ||||
1058 | oldval = getSignedBitfield(o->ptr,thisop->offset, | |||
1059 | thisop->bits); | |||
1060 | ||||
1061 | if (thisop->opcode == BITFIELDOP_INCRBY2) { | |||
1062 | newval = oldval + thisop->i64; | |||
1063 | overflow = checkSignedBitfieldOverflow(oldval, | |||
1064 | thisop->i64,thisop->bits,thisop->owtype,&wrapped); | |||
1065 | if (overflow) newval = wrapped; | |||
1066 | retval = newval; | |||
1067 | } else { | |||
1068 | newval = thisop->i64; | |||
1069 | overflow = checkSignedBitfieldOverflow(newval, | |||
1070 | 0,thisop->bits,thisop->owtype,&wrapped); | |||
1071 | if (overflow) newval = wrapped; | |||
1072 | retval = oldval; | |||
1073 | } | |||
1074 | ||||
1075 | /* On overflow of type is "FAIL", don't write and return | |||
1076 | * NULL to signal the condition. */ | |||
1077 | if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL2)) { | |||
1078 | addReplyLongLong(c,retval); | |||
1079 | setSignedBitfield(o->ptr,thisop->offset, | |||
1080 | thisop->bits,newval); | |||
1081 | } else { | |||
1082 | addReplyNull(c); | |||
1083 | } | |||
1084 | } else { | |||
1085 | uint64_t oldval, newval, wrapped, retval; | |||
1086 | int overflow; | |||
1087 | ||||
1088 | oldval = getUnsignedBitfield(o->ptr,thisop->offset, | |||
1089 | thisop->bits); | |||
1090 | ||||
1091 | if (thisop->opcode == BITFIELDOP_INCRBY2) { | |||
1092 | newval = oldval + thisop->i64; | |||
1093 | overflow = checkUnsignedBitfieldOverflow(oldval, | |||
1094 | thisop->i64,thisop->bits,thisop->owtype,&wrapped); | |||
1095 | if (overflow) newval = wrapped; | |||
1096 | retval = newval; | |||
1097 | } else { | |||
1098 | newval = thisop->i64; | |||
1099 | overflow = checkUnsignedBitfieldOverflow(newval, | |||
1100 | 0,thisop->bits,thisop->owtype,&wrapped); | |||
1101 | if (overflow) newval = wrapped; | |||
1102 | retval = oldval; | |||
1103 | } | |||
1104 | /* On overflow of type is "FAIL", don't write and return | |||
1105 | * NULL to signal the condition. */ | |||
1106 | if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL2)) { | |||
1107 | addReplyLongLong(c,retval); | |||
1108 | setUnsignedBitfield(o->ptr,thisop->offset, | |||
1109 | thisop->bits,newval); | |||
1110 | } else { | |||
1111 | addReplyNull(c); | |||
1112 | } | |||
1113 | } | |||
1114 | changes++; | |||
1115 | } else { | |||
1116 | /* GET */ | |||
1117 | unsigned char buf[9]; | |||
1118 | long strlen = 0; | |||
1119 | unsigned char *src = NULL((void*)0); | |||
1120 | char llbuf[LONG_STR_SIZE21]; | |||
1121 | ||||
1122 | if (o != NULL((void*)0)) | |||
1123 | src = getObjectReadOnlyString(o,&strlen,llbuf); | |||
1124 | ||||
1125 | /* For GET we use a trick: before executing the operation | |||
1126 | * copy up to 9 bytes to a local buffer, so that we can easily | |||
1127 | * execute up to 64 bit operations that are at actual string | |||
1128 | * object boundaries. */ | |||
1129 | memset(buf,0,9); | |||
1130 | int i; | |||
1131 | size_t byte = thisop->offset >> 3; | |||
1132 | for (i = 0; i < 9; i++) { | |||
1133 | if (src == NULL((void*)0) || i+byte >= (size_t)strlen) break; | |||
1134 | buf[i] = src[i+byte]; | |||
1135 | } | |||
1136 | ||||
1137 | /* Now operate on the copied buffer which is guaranteed | |||
1138 | * to be zero-padded. */ | |||
1139 | if (thisop->sign) { | |||
1140 | int64_t val = getSignedBitfield(buf,thisop->offset-(byte*8), | |||
1141 | thisop->bits); | |||
1142 | addReplyLongLong(c,val); | |||
1143 | } else { | |||
1144 | uint64_t val = getUnsignedBitfield(buf,thisop->offset-(byte*8), | |||
1145 | thisop->bits); | |||
1146 | addReplyLongLong(c,val); | |||
1147 | } | |||
1148 | } | |||
1149 | } | |||
1150 | ||||
1151 | if (changes) { | |||
1152 | signalModifiedKey(c,c->db,c->argv[1]); | |||
1153 | notifyKeyspaceEvent(NOTIFY_STRING(1<<3),"setbit",c->argv[1],c->db->id); | |||
1154 | server.dirty += changes; | |||
1155 | } | |||
1156 | zfree(ops); | |||
1157 | } | |||
1158 | ||||
1159 | void bitfieldCommand(client *c) { | |||
1160 | bitfieldGeneric(c, BITFIELD_FLAG_NONE0); | |||
1161 | } | |||
1162 | ||||
1163 | void bitfieldroCommand(client *c) { | |||
1164 | bitfieldGeneric(c, BITFIELD_FLAG_READONLY(1<<0)); | |||
1165 | } |