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. */
| 932 | * when flags is set to BITFIELD_FLAG_READONLY: in this case only the |
| 933 | * GET subcommand is allowed, other subcommands will return an error. */ |
| 934 | void bitfieldGeneric(client *c, int flags) { |
| 935 | robj *o; |
| 936 | uint64_t bitoffset; |
| 937 | int j, numops = 0, changes = 0; |
| 938 | struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */ |
| 939 | int owtype = BFOVERFLOW_WRAP; /* Overflow type. */ |
| 940 | int readonly = 1; |
| 941 | uint64_t highest_write_offset = 0; |
| 942 | |
| 943 | for (j = 2; j < c->argc; j++) { |
| 944 | int remargs = c->argc-j-1; /* Remaining args other than current. */ |
| 945 | char *subcmd = c->argv[j]->ptr; /* Current command name. */ |
| 946 | int opcode; /* Current operation code. */ |
| 947 | long long i64 = 0; /* Signed SET value. */ |
| 948 | int sign = 0; /* Signed or unsigned type? */ |
| 949 | int bits = 0; /* Bitfield width in bits. */ |
| 950 | |
| 951 | if (!strcasecmp(subcmd,"get") && remargs >= 2) |
| 952 | opcode = BITFIELDOP_GET; |
| 953 | else if (!strcasecmp(subcmd,"set") && remargs >= 3) |
| 954 | opcode = BITFIELDOP_SET; |
| 955 | else if (!strcasecmp(subcmd,"incrby") && remargs >= 3) |
| 956 | opcode = BITFIELDOP_INCRBY; |
| 957 | else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) { |
| 958 | char *owtypename = c->argv[j+1]->ptr; |
| 959 | j++; |
| 960 | if (!strcasecmp(owtypename,"wrap")) |
| 961 | owtype = BFOVERFLOW_WRAP; |
| 962 | else if (!strcasecmp(owtypename,"sat")) |
| 963 | owtype = BFOVERFLOW_SAT; |
| 964 | else if (!strcasecmp(owtypename,"fail")) |
| 965 | owtype = BFOVERFLOW_FAIL; |
| 966 | else { |
| 967 | addReplyError(c,"Invalid OVERFLOW type specified"); |
| 968 | zfree(ops); |
| 969 | return; |
| 970 | } |
| 971 | continue; |
| 972 | } else { |
| 973 | addReplyErrorObject(c,shared.syntaxerr); |
| 974 | zfree(ops); |
| 975 | return; |
| 976 | } |
| 977 | |
| 978 | /* Get the type and offset arguments, common to all the ops. */ |
| 979 | if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK) { |
| 980 | zfree(ops); |
| 981 | return; |
| 982 | } |
| 983 | |
| 984 | if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK){ |
| 985 | zfree(ops); |
| 986 | return; |
| 987 | } |
| 988 | |
| 989 | if (opcode != BITFIELDOP_GET) { |
| 990 | readonly = 0; |
| 991 | if (highest_write_offset < bitoffset + bits - 1) |
no test coverage detected