* The parseExtendedStringArgumentsOrReply() function performs the common validation for extended * string arguments used in SET and GET command. * * Get specific commands - PERSIST/DEL * Set specific commands - XX/NX/GET * Common commands - EX/EXAT/PX/PXAT/KEEPTTL * * Function takes pointers to client, flags, unit, pointer to pointer of expire obj if needed * to be determined and command_t
| 169 | * EX/EXAT/PX/PXAT arguments. Unit is updated to millisecond if PX/PXAT is set. |
| 170 | */ |
| 171 | int parseExtendedStringArgumentsOrReply(client *c, int *flags, int *unit, robj **expire, int command_type) { |
| 172 | |
| 173 | int j = command_type == COMMAND_GET ? 2 : 3; |
| 174 | for (; j < c->argc; j++) { |
| 175 | char *opt = c->argv[j]->ptr; |
| 176 | robj *next = (j == c->argc-1) ? NULL : c->argv[j+1]; |
| 177 | |
| 178 | if ((opt[0] == 'n' || opt[0] == 'N') && |
| 179 | (opt[1] == 'x' || opt[1] == 'X') && opt[2] == '\0' && |
| 180 | !(*flags & OBJ_SET_XX) && !(*flags & OBJ_SET_GET) && (command_type == COMMAND_SET)) |
| 181 | { |
| 182 | *flags |= OBJ_SET_NX; |
| 183 | } else if ((opt[0] == 'x' || opt[0] == 'X') && |
| 184 | (opt[1] == 'x' || opt[1] == 'X') && opt[2] == '\0' && |
| 185 | !(*flags & OBJ_SET_NX) && (command_type == COMMAND_SET)) |
| 186 | { |
| 187 | *flags |= OBJ_SET_XX; |
| 188 | } else if ((opt[0] == 'g' || opt[0] == 'G') && |
| 189 | (opt[1] == 'e' || opt[1] == 'E') && |
| 190 | (opt[2] == 't' || opt[2] == 'T') && opt[3] == '\0' && |
| 191 | !(*flags & OBJ_SET_NX) && (command_type == COMMAND_SET)) |
| 192 | { |
| 193 | *flags |= OBJ_SET_GET; |
| 194 | } else if (!strcasecmp(opt, "KEEPTTL") && !(*flags & OBJ_PERSIST) && |
| 195 | !(*flags & OBJ_EX) && !(*flags & OBJ_EXAT) && |
| 196 | !(*flags & OBJ_PX) && !(*flags & OBJ_PXAT) && (command_type == COMMAND_SET)) |
| 197 | { |
| 198 | *flags |= OBJ_KEEPTTL; |
| 199 | } else if (!strcasecmp(opt,"PERSIST") && (command_type == COMMAND_GET) && |
| 200 | !(*flags & OBJ_EX) && !(*flags & OBJ_EXAT) && |
| 201 | !(*flags & OBJ_PX) && !(*flags & OBJ_PXAT) && |
| 202 | !(*flags & OBJ_KEEPTTL)) |
| 203 | { |
| 204 | *flags |= OBJ_PERSIST; |
| 205 | } else if ((opt[0] == 'e' || opt[0] == 'E') && |
| 206 | (opt[1] == 'x' || opt[1] == 'X') && opt[2] == '\0' && |
| 207 | !(*flags & OBJ_KEEPTTL) && !(*flags & OBJ_PERSIST) && |
| 208 | !(*flags & OBJ_EXAT) && !(*flags & OBJ_PX) && |
| 209 | !(*flags & OBJ_PXAT) && next) |
| 210 | { |
| 211 | *flags |= OBJ_EX; |
| 212 | *expire = next; |
| 213 | j++; |
| 214 | } else if ((opt[0] == 'p' || opt[0] == 'P') && |
| 215 | (opt[1] == 'x' || opt[1] == 'X') && opt[2] == '\0' && |
| 216 | !(*flags & OBJ_KEEPTTL) && !(*flags & OBJ_PERSIST) && |
| 217 | !(*flags & OBJ_EX) && !(*flags & OBJ_EXAT) && |
| 218 | !(*flags & OBJ_PXAT) && next) |
| 219 | { |
| 220 | *flags |= OBJ_PX; |
| 221 | *unit = UNIT_MILLISECONDS; |
| 222 | *expire = next; |
| 223 | j++; |
| 224 | } else if ((opt[0] == 'e' || opt[0] == 'E') && |
| 225 | (opt[1] == 'x' || opt[1] == 'X') && |
| 226 | (opt[2] == 'a' || opt[2] == 'A') && |
| 227 | (opt[3] == 't' || opt[3] == 'T') && opt[4] == '\0' && |
| 228 | !(*flags & OBJ_KEEPTTL) && !(*flags & OBJ_PERSIST) && |
no test coverage detected