static*/
| 428 | |
| 429 | |
| 430 | /*static*/ string JSONDelta::createStringDelta(slice oldStr, slice nuuStr) { |
| 431 | if (nuuStr.size < gMinStringDiffLength |
| 432 | || (gCompatibleDeltas && oldStr.size > gMinStringDiffLength)) |
| 433 | return ""; |
| 434 | diff_match_patch<string> dmp; |
| 435 | dmp.Diff_Timeout = gTextDiffTimeout; |
| 436 | auto patches = dmp.patch_make(string(oldStr), string(nuuStr)); |
| 437 | |
| 438 | if (gCompatibleDeltas) |
| 439 | return dmp.patch_toText(patches); |
| 440 | |
| 441 | // Iterate over the diffs, writing the encoded form to the output stream: |
| 442 | stringstream diff; |
| 443 | long lastOldPos = 0, correction = 0; |
| 444 | for (auto patch = patches.begin(); patch != patches.end(); ++patch) { |
| 445 | long oldPos = patch->start1 + correction; // position in oldStr |
| 446 | long nuuPos = patch->start2; // position in nuuStr |
| 447 | auto &diffs = patch->diffs; |
| 448 | for (auto cur_diff = diffs.begin(); cur_diff != diffs.end(); ++cur_diff) { |
| 449 | auto length = cur_diff->text.length(); |
| 450 | if (cur_diff->operation == diff_match_patch<string>::EQUAL) { |
| 451 | oldPos += narrow_cast<long>(length); |
| 452 | nuuPos += narrow_cast<long>(length); |
| 453 | } else { |
| 454 | // Don't break up a UTF-8 multibyte character: |
| 455 | if (cur_diff->operation == diff_match_patch<string>::DELETE) |
| 456 | snapToUTF8Character(oldPos, length, oldStr); |
| 457 | else |
| 458 | snapToUTF8Character(nuuPos, length, nuuStr); |
| 459 | |
| 460 | assert(oldPos >= lastOldPos); |
| 461 | if (oldPos > lastOldPos) { |
| 462 | // Write the number of matching bytes since the last insert/delete: |
| 463 | diff << (oldPos-lastOldPos) << '='; |
| 464 | } |
| 465 | if (cur_diff->operation == diff_match_patch<string>::DELETE) { |
| 466 | // Write the number of deleted bytes: |
| 467 | diff << length << '-'; |
| 468 | oldPos += narrow_cast<long>(length); |
| 469 | } else /* INSERT */ { |
| 470 | // Write an insertion, both the count and the bytes: |
| 471 | diff << length << '+'; |
| 472 | diff.write((const char*)&nuuStr[nuuPos], length); |
| 473 | diff << '|'; |
| 474 | nuuPos += narrow_cast<long>(length); |
| 475 | } |
| 476 | lastOldPos = oldPos; |
| 477 | } |
| 478 | if ((size_t)diff.tellp() + 6 >= nuuStr.size) |
| 479 | return ""; // Patch is too long; give up on using a diff |
| 480 | } |
| 481 | correction += patch->length1 - patch->length2; |
| 482 | } |
| 483 | if (oldStr.size > size_t(lastOldPos)) { |
| 484 | // Write a final matching-bytes count: |
| 485 | diff << (oldStr.size-lastOldPos) << '='; |
| 486 | } |
| 487 | return diff.str(); |
nothing calls this directly
no test coverage detected