当前位置:网站首页>Gossip about redis source code 77
Gossip about redis source code 77
2022-07-03 23:24:00 【Tao song remains the same】
Here we mainly talk about bit field operation , You should have a deep understanding of basic bit operations :
/* The following set.*Bitfield and get.*Bitfield functions implement setting
* and getting arbitrary size (up to 64 bits) signed and unsigned integers
* at arbitrary positions into a bitmap.
*
* The representation considers the bitmap as having the bit number 0 to be
* the most significant bit of the first byte, and so forth, so for example
* setting a 5 bits unsigned integer to value 23 at offset 7 into a bitmap
* previously set to all zeroes, will produce the following representation:
*
* +--------+--------+
* |00000001|01110000|
* +--------+--------+
*
* When offsets and integer sizes are aligned to bytes boundaries, this is the
* same as big endian, however when such alignment does not exist, its important
* to also understand how the bits inside a byte are ordered.
*
* Note that this format follows the same convention as SETBIT and related
* commands.
*/
void setUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, uint64_t value) {
uint64_t byte, bit, byteval, bitval, j;
for (j = 0; j < bits; j++) {
bitval = (value & ((uint64_t)1<<(bits-1-j))) != 0;
byte = offset >> 3;
bit = 7 - (offset & 0x7);
byteval = p[byte];
byteval &= ~(1 << bit);
byteval |= bitval << bit;
p[byte] = byteval & 0xff;
offset++;
}
}
void setSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, int64_t value) {
uint64_t uv = value; /* Casting will add UINT64_MAX + 1 if v is negative. */
setUnsignedBitfield(p,offset,bits,uv);
}
uint64_t getUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {
uint64_t byte, bit, byteval, bitval, j, value = 0;
for (j = 0; j < bits; j++) {
byte = offset >> 3;
bit = 7 - (offset & 0x7);
byteval = p[byte];
bitval = (byteval >> bit) & 1;
value = (value<<1) | bitval;
offset++;
}
return value;
}
int64_t getSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {
int64_t value;
union {uint64_t u; int64_t i;} conv;
/* Converting from unsigned to signed is undefined when the value does
* not fit, however here we assume two's complement and the original value
* was obtained from signed -> unsigned conversion, so we'll find the
* most significant bit set if the original value was negative.
*
* Note that two's complement is mandatory for exact-width types
* according to the C99 standard. */
conv.u = getUnsignedBitfield(p,offset,bits);
value = conv.i;
/* If the top significant bit is 1, propagate it to all the
* higher bits for two's complement representation of signed
* integers. */
if (bits < 64 && (value & ((uint64_t)1 << (bits-1))))
value |= ((uint64_t)-1) << bits;
return value;
}
/* The following two functions detect overflow of a value in the context
* of storing it as an unsigned or signed integer with the specified
* number of bits. The functions both take the value and a possible increment.
* If no overflow could happen and the value+increment fit inside the limits,
* then zero is returned, otherwise in case of overflow, 1 is returned,
* otherwise in case of underflow, -1 is returned.
*
* When non-zero is returned (overflow or underflow), if not NULL, *limit is
* set to the value the operation should result when an overflow happens,
* depending on the specified overflow semantics:
*
* For BFOVERFLOW_SAT if 1 is returned, *limit it is set maximum value that
* you can store in that integer. when -1 is returned, *limit is set to the
* minimum value that an integer of that size can represent.
*
* For BFOVERFLOW_WRAP *limit is set by performing the operation in order to
* "wrap" around towards zero for unsigned integers, or towards the most
* negative number that is possible to represent for signed integers. */
#define BFOVERFLOW_WRAP 0
#define BFOVERFLOW_SAT 1
#define BFOVERFLOW_FAIL 2 /* Used by the BITFIELD command implementation. */
int checkUnsignedBitfieldOverflow(uint64_t value, int64_t incr, uint64_t bits, int owtype, uint64_t *limit) {
uint64_t max = (bits == 64) ? UINT64_MAX : (((uint64_t)1<<bits)-1);
int64_t maxincr = max-value;
int64_t minincr = -value;
if (value > max || (incr > 0 && incr > maxincr)) {
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
} else if (owtype == BFOVERFLOW_SAT) {
*limit = max;
}
}
return 1;
} else if (incr < 0 && incr < minincr) {
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
} else if (owtype == BFOVERFLOW_SAT) {
*limit = 0;
}
}
return -1;
}
return 0;
handle_wrap:
{
uint64_t mask = ((uint64_t)-1) << bits;
uint64_t res = value+incr;
res &= ~mask;
*limit = res;
}
return 1;
}
int checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int owtype, int64_t *limit) {
int64_t max = (bits == 64) ? INT64_MAX : (((int64_t)1<<(bits-1))-1);
int64_t min = (-max)-1;
/* Note that maxincr and minincr could overflow, but we use the values
* only after checking 'value' range, so when we use it no overflow
* happens. */
int64_t maxincr = max-value;
int64_t minincr = min-value;
if (value > max || (bits != 64 && incr > maxincr) || (value >= 0 && incr > 0 && incr > maxincr))
{
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
} else if (owtype == BFOVERFLOW_SAT) {
*limit = max;
}
}
return 1;
} else if (value < min || (bits != 64 && incr < minincr) || (value < 0 && incr < 0 && incr < minincr)) {
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
} else if (owtype == BFOVERFLOW_SAT) {
*limit = min;
}
}
return -1;
}
return 0;
handle_wrap:
{
uint64_t msb = (uint64_t)1 << (bits-1);
uint64_t a = value, b = incr, c;
c = a+b; /* Perform addition as unsigned so that's defined. */
/* If the sign bit is set, propagate to all the higher order
* bits, to cap the negative value. If it's clear, mask to
* the positive integer limit. */
if (bits < 64) {
uint64_t mask = ((uint64_t)-1) << bits;
if (c & msb) {
c |= mask;
} else {
c &= ~mask;
}
}
*limit = c;
}
return 1;
}
/* Debugging function. Just show bits in the specified bitmap. Not used
* but here for not having to rewrite it when debugging is needed. */
void printBits(unsigned char *p, unsigned long count) {
unsigned long j, i, byte;
for (j = 0; j < count; j++) {
byte = p[j];
for (i = 0x80; i > 0; i /= 2)
printf("%c", (byte & i) ? '1' : '0');
printf("|");
}
printf("\n");
}
/* -----------------------------------------------------------------------------
* Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP.
* -------------------------------------------------------------------------- */
#define BITOP_AND 0
#define BITOP_OR 1
#define BITOP_XOR 2
#define BITOP_NOT 3
#define BITFIELDOP_GET 0
#define BITFIELDOP_SET 1
#define BITFIELDOP_INCRBY 2
/* This helper function used by GETBIT / SETBIT parses the bit offset argument
* making sure an error is returned if it is negative or if it overflows
* Redis 512 MB limit for the string value or more (server.proto_max_bulk_len).
*
* If the 'hash' argument is true, and 'bits is positive, then the command
* will also parse bit offsets prefixed by "#". In such a case the offset
* is multiplied by 'bits'. This is useful for the BITFIELD command. */
int getBitOffsetFromArgument(client *c, robj *o, uint64_t *offset, int hash, int bits) {
long long loffset;
char *err = "bit offset is not an integer or out of range";
char *p = o->ptr;
size_t plen = sdslen(p);
int usehash = 0;
/* Handle #<offset> form. */
if (p[0] == '#' && hash && bits > 0) usehash = 1;
if (string2ll(p+usehash,plen-usehash,&loffset) == 0) {
addReplyError(c,err);
return C_ERR;
}
/* Adjust the offset by 'bits' for #<offset> form. */
if (usehash) loffset *= bits;
/* Limit offset to server.proto_max_bulk_len (512MB in bytes by default) */
if ((loffset < 0) || (loffset >> 3) >= server.proto_max_bulk_len)
{
addReplyError(c,err);
return C_ERR;
}
*offset = loffset;
return C_OK;
}
/* This helper function for BITFIELD parses a bitfield type in the form
* <sign><bits> where sign is 'u' or 'i' for unsigned and signed, and
* the bits is a value between 1 and 64. However 64 bits unsigned integers
* are reported as an error because of current limitations of Redis protocol
* to return unsigned integer values greater than INT64_MAX.
*
* On error C_ERR is returned and an error is sent to the client. */
int getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {
char *p = o->ptr;
char *err = "Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is.";
long long llbits;
if (p[0] == 'i') {
*sign = 1;
} else if (p[0] == 'u') {
*sign = 0;
} else {
addReplyError(c,err);
return C_ERR;
}
if ((string2ll(p+1,strlen(p+1),&llbits)) == 0 ||
llbits < 1 ||
(*sign == 1 && llbits > 64) ||
(*sign == 0 && llbits > 63))
{
addReplyError(c,err);
return C_ERR;
}
*bits = llbits;
return C_OK;
}
边栏推荐
- Alibaba cloud container service differentiation SLO hybrid technology practice
- 炒股开户佣金优惠怎么才能获得,网上开户安全吗
- File copy method
- What are the common computer problems and solutions
- Current detection circuit - including op amp current scheme
- Hcip day 15 notes
- [MySQL] classification of multi table queries
- Maxwell equation and Euler formula - link
- Qtoolbutton available signal
- Hcip day 14 notes
猜你喜欢
How can enterprises and developers take advantage of the explosion of cloud native landing?
The difference between single power amplifier and dual power amplifier
Weekly leetcode - nc9/nc56/nc89/nc126/nc69/nc120
Hcip 13th day notes
Selenium check box
MLX90614 driver, function introduction and PEC verification
Blue Bridge Cup -- Mason prime
2022 t elevator repair registration examination and the latest analysis of T elevator repair
Ningde times and BYD have refuted rumors one after another. Why does someone always want to harm domestic brands?
EPF: a fuzzy testing framework for network protocols based on evolution, protocol awareness and coverage guidance
随机推荐
2022 examination of safety production management personnel of hazardous chemical production units and examination skills of safety production management personnel of hazardous chemical production unit
Fluent learning (5) GridView
NPM script
2022 t elevator repair registration examination and the latest analysis of T elevator repair
[MySQL] classification of multi table queries
Subset enumeration method
C3p0 connection MySQL 8.0.11 configuration problem
股票开户佣金最低的券商有哪些大家推荐一下,手机上开户安全吗
Exclusive download! Alibaba cloud native brings 10 + technical experts to bring "new possibilities of cloud native and cloud future"
. Net ADO splicing SQL statement with parameters
How to solve the problem of computer networking but showing no Internet connection
540. Single element in ordered array
Apple released a supplementary update to MacOS Catalina 10.15.5, which mainly fixes security vulnerabilities
Gorilla/mux framework (RK boot): add tracing Middleware
Op amp related - link
Qtoolbutton - menu and popup mode
[Android reverse] use DB browser to view and modify SQLite database (download DB browser installation package | install DB browser tool)
Mongoose the table associated with the primary key, and automatically bring out the data of another table
Enter MySQL in docker container by command under Linux
[Happy Valentine's day] "I still like you very much, like sin ² a+cos ² A consistent "(white code in the attached table)