This implements both the BITFIELD command and the BITFIELD_RO command * when flags is set to BITFIELD_FLAG_READONLY: in this case only the * GET subcommand is allowed, other subcommands will return an error. */
| 1014 | * when flags is set to BITFIELD_FLAG_READONLY: in this case only the |
| 1015 | * GET subcommand is allowed, other subcommands will return an error. */ |
| 1016 | void bitfieldGeneric(client *c, int flags) { |
| 1017 | robj_roptr o; |
| 1018 | uint64_t bitoffset; |
| 1019 | int j, numops = 0, changes = 0; |
| 1020 | struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */ |
| 1021 | int owtype = BFOVERFLOW_WRAP; /* Overflow type. */ |
| 1022 | int readonly = 1; |
| 1023 | uint64_t highest_write_offset = 0; |
| 1024 | |
| 1025 | for (j = 2; j < c->argc; j++) { |
| 1026 | int remargs = c->argc-j-1; /* Remaining args other than current. */ |
| 1027 | char *subcmd = szFromObj(c->argv[j]); /* Current command name. */ |
| 1028 | int opcode; /* Current operation code. */ |
| 1029 | long long i64 = 0; /* Signed SET value. */ |
| 1030 | int sign = 0; /* Signed or unsigned type? */ |
| 1031 | int bits = 0; /* Bitfield width in bits. */ |
| 1032 | |
| 1033 | if (!strcasecmp(subcmd,"get") && remargs >= 2) |
| 1034 | opcode = BITFIELDOP_GET; |
| 1035 | else if (!strcasecmp(subcmd,"set") && remargs >= 3) |
| 1036 | opcode = BITFIELDOP_SET; |
| 1037 | else if (!strcasecmp(subcmd,"incrby") && remargs >= 3) |
| 1038 | opcode = BITFIELDOP_INCRBY; |
| 1039 | else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) { |
| 1040 | char *owtypename = szFromObj(c->argv[j+1]); |
| 1041 | j++; |
| 1042 | if (!strcasecmp(owtypename,"wrap")) |
| 1043 | owtype = BFOVERFLOW_WRAP; |
| 1044 | else if (!strcasecmp(owtypename,"sat")) |
| 1045 | owtype = BFOVERFLOW_SAT; |
| 1046 | else if (!strcasecmp(owtypename,"fail")) |
| 1047 | owtype = BFOVERFLOW_FAIL; |
| 1048 | else { |
| 1049 | addReplyError(c,"Invalid OVERFLOW type specified"); |
| 1050 | zfree(ops); |
| 1051 | return; |
| 1052 | } |
| 1053 | continue; |
| 1054 | } else { |
| 1055 | addReplyErrorObject(c,shared.syntaxerr); |
| 1056 | zfree(ops); |
| 1057 | return; |
| 1058 | } |
| 1059 | |
| 1060 | /* Get the type and offset arguments, common to all the ops. */ |
| 1061 | if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK) { |
| 1062 | zfree(ops); |
| 1063 | return; |
| 1064 | } |
| 1065 | |
| 1066 | if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK){ |
| 1067 | zfree(ops); |
| 1068 | return; |
| 1069 | } |
| 1070 | |
| 1071 | if (opcode != BITFIELDOP_GET) { |
| 1072 | readonly = 0; |
| 1073 | if (highest_write_offset < bitoffset + bits - 1) |
no test coverage detected