BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
| 591 | |
| 592 | /* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */ |
| 593 | void bitopCommand(client *c) { |
| 594 | char *opname = c->argv[1]->ptr; |
| 595 | robj *o, *targetkey = c->argv[2]; |
| 596 | unsigned long op, j, numkeys; |
| 597 | robj **objects; /* Array of source objects. */ |
| 598 | unsigned char **src; /* Array of source strings pointers. */ |
| 599 | unsigned long *len, maxlen = 0; /* Array of length of src strings, |
| 600 | and max len. */ |
| 601 | unsigned long minlen = 0; /* Min len among the input keys. */ |
| 602 | unsigned char *res = NULL; /* Resulting string. */ |
| 603 | |
| 604 | /* Parse the operation name. */ |
| 605 | if ((opname[0] == 'a' || opname[0] == 'A') && !strcasecmp(opname,"and")) |
| 606 | op = BITOP_AND; |
| 607 | else if((opname[0] == 'o' || opname[0] == 'O') && !strcasecmp(opname,"or")) |
| 608 | op = BITOP_OR; |
| 609 | else if((opname[0] == 'x' || opname[0] == 'X') && !strcasecmp(opname,"xor")) |
| 610 | op = BITOP_XOR; |
| 611 | else if((opname[0] == 'n' || opname[0] == 'N') && !strcasecmp(opname,"not")) |
| 612 | op = BITOP_NOT; |
| 613 | else { |
| 614 | addReplyErrorObject(c,shared.syntaxerr); |
| 615 | return; |
| 616 | } |
| 617 | |
| 618 | /* Sanity check: NOT accepts only a single key argument. */ |
| 619 | if (op == BITOP_NOT && c->argc != 4) { |
| 620 | addReplyError(c,"BITOP NOT must be called with a single source key."); |
| 621 | return; |
| 622 | } |
| 623 | |
| 624 | /* Lookup keys, and store pointers to the string objects into an array. */ |
| 625 | numkeys = c->argc - 3; |
| 626 | src = zmalloc(sizeof(unsigned char*) * numkeys); |
| 627 | len = zmalloc(sizeof(long) * numkeys); |
| 628 | objects = zmalloc(sizeof(robj*) * numkeys); |
| 629 | for (j = 0; j < numkeys; j++) { |
| 630 | o = lookupKeyRead(c->db,c->argv[j+3]); |
| 631 | /* Handle non-existing keys as empty strings. */ |
| 632 | if (o == NULL) { |
| 633 | objects[j] = NULL; |
| 634 | src[j] = NULL; |
| 635 | len[j] = 0; |
| 636 | minlen = 0; |
| 637 | continue; |
| 638 | } |
| 639 | /* Return an error if one of the keys is not a string. */ |
| 640 | if (checkType(c,o,OBJ_STRING)) { |
| 641 | unsigned long i; |
| 642 | for (i = 0; i < j; i++) { |
| 643 | if (objects[i]) |
| 644 | decrRefCount(objects[i]); |
| 645 | } |
| 646 | zfree(src); |
| 647 | zfree(len); |
| 648 | zfree(objects); |
| 649 | return; |
| 650 | } |
nothing calls this directly
no test coverage detected