]>
git.saurik.com Git - redis.git/blob - zip.c
6 #define ZIP_ENC_SHORT 1
8 #define ZIP_ENC_LLONG 3
9 #define ZIP_ENCODING(p) ((p)[0] >> 6)
11 /* Length encoding for raw entries */
12 #define ZIP_LEN_INLINE 0
13 #define ZIP_LEN_UINT16 1
14 #define ZIP_LEN_UINT32 2
16 static unsigned int zipEncodingSize(char encoding
) {
17 if (encoding
== ZIP_ENC_SHORT
) {
18 return sizeof(short int);
19 } else if (encoding
== ZIP_ENC_INT
) {
21 } else if (encoding
== ZIP_ENC_LLONG
) {
22 return sizeof(long long);
27 /* Decode the encoded length pointed by 'p'. If a pointer to 'lensize' is
28 * provided, it is set to the number of bytes required to encode the length. */
29 static unsigned int zipDecodeLength(unsigned char *p
, unsigned int *lensize
) {
30 unsigned char encoding
= ZIP_ENCODING(p
), lenenc
;
33 if (encoding
== ZIP_ENC_RAW
) {
34 lenenc
= (p
[0] >> 4) & 0x3;
35 if (lenenc
== ZIP_LEN_INLINE
) {
37 if (lensize
) *lensize
= 1;
38 } else if (lenenc
== ZIP_LEN_UINT16
) {
39 len
= p
[1] | (p
[2] << 8);
40 if (lensize
) *lensize
= 3;
42 len
= p
[1] | (p
[2] << 8) | (p
[3] << 16) | (p
[4] << 24);
43 if (lensize
) *lensize
= 5;
46 len
= zipEncodingSize(encoding
);
47 if (lensize
) *lensize
= 1;
52 /* Encode the length 'l' writing it in 'p'. If p is NULL it just returns
53 * the amount of bytes required to encode such a length. */
54 static unsigned int zipEncodeLength(unsigned char *p
, char encoding
, unsigned int rawlen
) {
55 unsigned char len
= 1, lenenc
, buf
[5];
56 if (encoding
== ZIP_ENC_RAW
) {
59 lenenc
= ZIP_LEN_INLINE
;
61 } else if (rawlen
<= 0xffff) {
64 lenenc
= ZIP_LEN_UINT16
;
65 buf
[1] = (rawlen
) & 0xff;
66 buf
[2] = (rawlen
>> 8) & 0xff;
70 lenenc
= ZIP_LEN_UINT32
;
71 buf
[1] = (rawlen
) & 0xff;
72 buf
[2] = (rawlen
>> 8) & 0xff;
73 buf
[3] = (rawlen
>> 16) & 0xff;
74 buf
[4] = (rawlen
>> 24) & 0xff;
76 buf
[0] = (lenenc
<< 4) | (buf
[0] & 0xf);
80 /* Apparently we need to store the length in 'p' */
81 buf
[0] = (encoding
<< 6) | (buf
[0] & 0x3f);
86 /* Check if string pointed to by 'entry' can be encoded as an integer.
87 * Stores the integer value in 'v' and its encoding in 'encoding'.
88 * Warning: this function requires a NULL-terminated string! */
89 static int zipTryEncoding(unsigned char *entry
, long long *v
, char *encoding
) {
93 if (entry
[0] == '-' || (entry
[0] >= '0' && entry
[0] <= '9')) {
94 value
= strtoll(entry
,&eptr
,10);
95 if (eptr
[0] != '\0') return 0;
96 if (value
>= SHRT_MIN
&& value
<= SHRT_MAX
) {
97 *encoding
= ZIP_ENC_SHORT
;
98 } else if (value
>= INT_MIN
&& value
<= INT_MAX
) {
99 *encoding
= ZIP_ENC_INT
;
101 *encoding
= ZIP_ENC_LLONG
;
109 static void zipSaveInteger(unsigned char *p
, long long value
, char encoding
) {
113 if (encoding
== ZIP_ENC_SHORT
) {
115 memcpy(p
,&s
,sizeof(s
));
116 } else if (encoding
== ZIP_ENC_INT
) {
118 memcpy(p
,&i
,sizeof(i
));
119 } else if (encoding
== ZIP_ENC_LLONG
) {
121 memcpy(p
,&l
,sizeof(l
));
127 static long long zipLoadInteger(unsigned char *p
, char encoding
) {
131 if (encoding
== ZIP_ENC_SHORT
) {
132 memcpy(&s
,p
,sizeof(s
));
134 } else if (encoding
== ZIP_ENC_INT
) {
135 memcpy(&i
,p
,sizeof(i
));
137 } else if (encoding
== ZIP_ENC_LLONG
) {
138 memcpy(&l
,p
,sizeof(l
));
146 /* Return the total amount used by an entry (encoded length + payload). */
147 static unsigned int zipRawEntryLength(unsigned char *p
) {
148 unsigned int lensize
, len
;
149 len
= zipDecodeLength(p
, &lensize
);
150 return lensize
+ len
;
153 /* Resize the zip* structure. */
154 static unsigned char *zipResize(unsigned char *z
, unsigned int len
) {