Add a new element or update the score of an existing element in a sorted * set, regardless of its encoding. * * The set of flags change the command behavior. * * The input flags are the following: * * ZADD_INCR: Increment the current element score by 'score' instead of updating * the current element score. If the element does not exist, we * assume 0 as previous sco
| 1322 | * The function does not take ownership of the 'ele' SDS string, but copies |
| 1323 | * it if needed. */ |
| 1324 | int zsetAdd(robj *zobj, double score, sds ele, int in_flags, int *out_flags, double *newscore) { |
| 1325 | /* Turn options into simple to check vars. */ |
| 1326 | int incr = (in_flags & ZADD_IN_INCR) != 0; |
| 1327 | int nx = (in_flags & ZADD_IN_NX) != 0; |
| 1328 | int xx = (in_flags & ZADD_IN_XX) != 0; |
| 1329 | int gt = (in_flags & ZADD_IN_GT) != 0; |
| 1330 | int lt = (in_flags & ZADD_IN_LT) != 0; |
| 1331 | *out_flags = 0; /* We'll return our response flags. */ |
| 1332 | double curscore; |
| 1333 | |
| 1334 | /* NaN as input is an error regardless of all the other parameters. */ |
| 1335 | if (std::isnan(score)) { |
| 1336 | *out_flags = ZADD_OUT_NAN; |
| 1337 | return 0; |
| 1338 | } |
| 1339 | |
| 1340 | /* Update the sorted set according to its encoding. */ |
| 1341 | if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { |
| 1342 | unsigned char *eptr; |
| 1343 | |
| 1344 | if ((eptr = zzlFind((unsigned char*)zobj->m_ptr,ele,&curscore)) != NULL) { |
| 1345 | /* NX? Return, same element already exists. */ |
| 1346 | if (nx) { |
| 1347 | *out_flags |= ZADD_OUT_NOP; |
| 1348 | return 1; |
| 1349 | } |
| 1350 | |
| 1351 | /* Prepare the score for the increment if needed. */ |
| 1352 | if (incr) { |
| 1353 | score += curscore; |
| 1354 | if (std::isnan(score)) { |
| 1355 | *out_flags |= ZADD_OUT_NAN; |
| 1356 | return 0; |
| 1357 | } |
| 1358 | } |
| 1359 | |
| 1360 | /* GT/LT? Only update if score is greater/less than current. */ |
| 1361 | if ((lt && score >= curscore) || (gt && score <= curscore)) { |
| 1362 | *out_flags |= ZADD_OUT_NOP; |
| 1363 | return 1; |
| 1364 | } |
| 1365 | |
| 1366 | if (newscore) *newscore = score; |
| 1367 | |
| 1368 | /* Remove and re-insert when score changed. */ |
| 1369 | if (score != curscore) { |
| 1370 | zobj->m_ptr = zzlDelete((unsigned char*)zobj->m_ptr,eptr); |
| 1371 | zobj->m_ptr = zzlInsert((unsigned char*)zobj->m_ptr,ele,score); |
| 1372 | *out_flags |= ZADD_OUT_UPDATED; |
| 1373 | } |
| 1374 | return 1; |
| 1375 | } else if (!xx) { |
| 1376 | /* check if the element is too large or the list |
| 1377 | * becomes too long *before* executing zzlInsert. */ |
| 1378 | if (zzlLength((unsigned char*)ptrFromObj(zobj))+1 > g_pserver->zset_max_ziplist_entries || |
| 1379 | sdslen(ele) > g_pserver->zset_max_ziplist_value || |
| 1380 | !ziplistSafeToAdd((unsigned char *)ptrFromObj(zobj), sdslen(ele))) |
| 1381 | { |
no test coverage detected