]>
git.saurik.com Git - redis.git/blob - src/t_string.c
3 /*-----------------------------------------------------------------------------
5 *----------------------------------------------------------------------------*/
7 void setGenericCommand(redisClient
*c
, int nx
, robj
*key
, robj
*val
, robj
*expire
) {
9 long seconds
= 0; /* initialized to avoid an harmness warning */
12 if (getLongFromObjectOrReply(c
, expire
, &seconds
, NULL
) != REDIS_OK
)
15 addReplySds(c
,sdsnew("-ERR invalid expire time in SETEX\r\n"));
20 if (nx
) deleteIfVolatile(c
->db
,key
);
21 retval
= dbAdd(c
->db
,key
,val
);
22 if (retval
== REDIS_ERR
) {
24 dbReplace(c
->db
,key
,val
);
27 addReply(c
,shared
.czero
);
33 touchWatchedKey(c
->db
,key
);
35 removeExpire(c
->db
,key
);
36 if (expire
) setExpire(c
->db
,key
,time(NULL
)+seconds
);
37 addReply(c
, nx
? shared
.cone
: shared
.ok
);
40 void setCommand(redisClient
*c
) {
41 setGenericCommand(c
,0,c
->argv
[1],c
->argv
[2],NULL
);
44 void setnxCommand(redisClient
*c
) {
45 setGenericCommand(c
,1,c
->argv
[1],c
->argv
[2],NULL
);
48 void setexCommand(redisClient
*c
) {
49 setGenericCommand(c
,0,c
->argv
[1],c
->argv
[3],c
->argv
[2]);
52 int getGenericCommand(redisClient
*c
) {
55 if ((o
= lookupKeyReadOrReply(c
,c
->argv
[1],shared
.nullbulk
)) == NULL
)
58 if (o
->type
!= REDIS_STRING
) {
59 addReply(c
,shared
.wrongtypeerr
);
67 void getCommand(redisClient
*c
) {
71 void getsetCommand(redisClient
*c
) {
72 if (getGenericCommand(c
) == REDIS_ERR
) return;
73 dbReplace(c
->db
,c
->argv
[1],c
->argv
[2]);
74 incrRefCount(c
->argv
[2]);
75 touchWatchedKey(c
->db
,c
->argv
[1]);
77 removeExpire(c
->db
,c
->argv
[1]);
80 void mgetCommand(redisClient
*c
) {
83 addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",c
->argc
-1));
84 for (j
= 1; j
< c
->argc
; j
++) {
85 robj
*o
= lookupKeyRead(c
->db
,c
->argv
[j
]);
87 addReply(c
,shared
.nullbulk
);
89 if (o
->type
!= REDIS_STRING
) {
90 addReply(c
,shared
.nullbulk
);
98 void msetGenericCommand(redisClient
*c
, int nx
) {
101 if ((c
->argc
% 2) == 0) {
102 addReplySds(c
,sdsnew("-ERR wrong number of arguments for MSET\r\n"));
105 /* Handle the NX flag. The MSETNX semantic is to return zero and don't
106 * set nothing at all if at least one already key exists. */
108 for (j
= 1; j
< c
->argc
; j
+= 2) {
109 if (lookupKeyWrite(c
->db
,c
->argv
[j
]) != NULL
) {
115 addReply(c
, shared
.czero
);
119 for (j
= 1; j
< c
->argc
; j
+= 2) {
120 c
->argv
[j
+1] = tryObjectEncoding(c
->argv
[j
+1]);
121 dbReplace(c
->db
,c
->argv
[j
],c
->argv
[j
+1]);
122 incrRefCount(c
->argv
[j
+1]);
123 removeExpire(c
->db
,c
->argv
[j
]);
124 touchWatchedKey(c
->db
,c
->argv
[j
]);
126 server
.dirty
+= (c
->argc
-1)/2;
127 addReply(c
, nx
? shared
.cone
: shared
.ok
);
130 void msetCommand(redisClient
*c
) {
131 msetGenericCommand(c
,0);
134 void msetnxCommand(redisClient
*c
) {
135 msetGenericCommand(c
,1);
138 void incrDecrCommand(redisClient
*c
, long long incr
) {
142 o
= lookupKeyWrite(c
->db
,c
->argv
[1]);
143 if (o
!= NULL
&& checkType(c
,o
,REDIS_STRING
)) return;
144 if (getLongLongFromObjectOrReply(c
,o
,&value
,NULL
) != REDIS_OK
) return;
147 o
= createStringObjectFromLongLong(value
);
148 dbReplace(c
->db
,c
->argv
[1],o
);
149 touchWatchedKey(c
->db
,c
->argv
[1]);
151 addReply(c
,shared
.colon
);
153 addReply(c
,shared
.crlf
);
156 void incrCommand(redisClient
*c
) {
157 incrDecrCommand(c
,1);
160 void decrCommand(redisClient
*c
) {
161 incrDecrCommand(c
,-1);
164 void incrbyCommand(redisClient
*c
) {
167 if (getLongLongFromObjectOrReply(c
, c
->argv
[2], &incr
, NULL
) != REDIS_OK
) return;
168 incrDecrCommand(c
,incr
);
171 void decrbyCommand(redisClient
*c
) {
174 if (getLongLongFromObjectOrReply(c
, c
->argv
[2], &incr
, NULL
) != REDIS_OK
) return;
175 incrDecrCommand(c
,-incr
);
178 void appendCommand(redisClient
*c
) {
183 o
= lookupKeyWrite(c
->db
,c
->argv
[1]);
186 retval
= dbAdd(c
->db
,c
->argv
[1],c
->argv
[2]);
187 incrRefCount(c
->argv
[2]);
188 totlen
= stringObjectLen(c
->argv
[2]);
190 if (o
->type
!= REDIS_STRING
) {
191 addReply(c
,shared
.wrongtypeerr
);
194 /* If the object is specially encoded or shared we have to make
196 if (o
->refcount
!= 1 || o
->encoding
!= REDIS_ENCODING_RAW
) {
197 robj
*decoded
= getDecodedObject(o
);
199 o
= createStringObject(decoded
->ptr
, sdslen(decoded
->ptr
));
200 decrRefCount(decoded
);
201 dbReplace(c
->db
,c
->argv
[1],o
);
204 if (c
->argv
[2]->encoding
== REDIS_ENCODING_RAW
) {
205 o
->ptr
= sdscatlen(o
->ptr
,
206 c
->argv
[2]->ptr
, sdslen(c
->argv
[2]->ptr
));
208 o
->ptr
= sdscatprintf(o
->ptr
, "%ld",
209 (unsigned long) c
->argv
[2]->ptr
);
211 totlen
= sdslen(o
->ptr
);
213 touchWatchedKey(c
->db
,c
->argv
[1]);
215 addReplySds(c
,sdscatprintf(sdsempty(),":%lu\r\n",(unsigned long)totlen
));
218 void substrCommand(redisClient
*c
) {
220 long start
= atoi(c
->argv
[2]->ptr
);
221 long end
= atoi(c
->argv
[3]->ptr
);
222 size_t rangelen
, strlen
;
225 if ((o
= lookupKeyReadOrReply(c
,c
->argv
[1],shared
.nullbulk
)) == NULL
||
226 checkType(c
,o
,REDIS_STRING
)) return;
228 o
= getDecodedObject(o
);
229 strlen
= sdslen(o
->ptr
);
231 /* convert negative indexes */
232 if (start
< 0) start
= strlen
+start
;
233 if (end
< 0) end
= strlen
+end
;
234 if (start
< 0) start
= 0;
235 if (end
< 0) end
= 0;
237 /* indexes sanity checks */
238 if (start
> end
|| (size_t)start
>= strlen
) {
239 /* Out of range start or start > end result in null reply */
240 addReply(c
,shared
.nullbulk
);
244 if ((size_t)end
>= strlen
) end
= strlen
-1;
245 rangelen
= (end
-start
)+1;
247 /* Return the result */
248 addReplySds(c
,sdscatprintf(sdsempty(),"$%zu\r\n",rangelen
));
249 range
= sdsnewlen((char*)o
->ptr
+start
,rangelen
);
250 addReplySds(c
,range
);
251 addReply(c
,shared
.crlf
);