| 721 | } |
| 722 | |
| 723 | void hincrbyfloatCommand(client *c) { |
| 724 | long double value, incr; |
| 725 | long long ll; |
| 726 | robj *o; |
| 727 | sds new; |
| 728 | unsigned char *vstr; |
| 729 | unsigned int vlen; |
| 730 | |
| 731 | if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return; |
| 732 | if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return; |
| 733 | if (hashTypeGetValue(o,c->argv[2]->ptr,&vstr,&vlen,&ll) == C_OK) { |
| 734 | if (vstr) { |
| 735 | if (string2ld((char*)vstr,vlen,&value) == 0) { |
| 736 | addReplyError(c,"hash value is not a float"); |
| 737 | return; |
| 738 | } |
| 739 | } else { |
| 740 | value = (long double)ll; |
| 741 | } |
| 742 | } else { |
| 743 | value = 0; |
| 744 | } |
| 745 | |
| 746 | value += incr; |
| 747 | if (isnan(value) || isinf(value)) { |
| 748 | addReplyError(c,"increment would produce NaN or Infinity"); |
| 749 | return; |
| 750 | } |
| 751 | |
| 752 | char buf[MAX_LONG_DOUBLE_CHARS]; |
| 753 | int len = ld2string(buf,sizeof(buf),value,LD_STR_HUMAN); |
| 754 | new = sdsnewlen(buf,len); |
| 755 | hashTypeSet(o,c->argv[2]->ptr,new,HASH_SET_TAKE_VALUE); |
| 756 | addReplyBulkCBuffer(c,buf,len); |
| 757 | signalModifiedKey(c,c->db,c->argv[1]); |
| 758 | notifyKeyspaceEvent(NOTIFY_HASH,"hincrbyfloat",c->argv[1],c->db->id); |
| 759 | server.dirty++; |
| 760 | |
| 761 | /* Always replicate HINCRBYFLOAT as an HSET command with the final value |
| 762 | * in order to make sure that differences in float precision or formatting |
| 763 | * will not create differences in replicas or after an AOF restart. */ |
| 764 | robj *newobj; |
| 765 | newobj = createRawStringObject(buf,len); |
| 766 | rewriteClientCommandArgument(c,0,shared.hset); |
| 767 | rewriteClientCommandArgument(c,3,newobj); |
| 768 | decrRefCount(newobj); |
| 769 | } |
| 770 | |
| 771 | static void addHashFieldToReply(client *c, robj *o, sds field) { |
| 772 | int ret; |
nothing calls this directly
no test coverage detected