| 1561 | */ |
| 1562 | public: |
| 1563 | static Diffs diff_fromDelta(const string_t &text1, const string_t &delta) { |
| 1564 | Diffs diffs; |
| 1565 | ssize_t pointer = 0; // Cursor in text1 |
| 1566 | typename string_t::size_type token_len; |
| 1567 | for (typename string_t::const_pointer token = delta.c_str(); token - delta.c_str() < (ssize_t)delta.length(); token += token_len + 1) { |
| 1568 | token_len = next_token(delta, traits::from_wchar(L'\t'), token); |
| 1569 | if (token_len == 0) { |
| 1570 | // Blank tokens are ok (from a trailing \t). |
| 1571 | continue; |
| 1572 | } |
| 1573 | // Each token begins with a one character parameter which specifies the |
| 1574 | // operation of this token (delete, insert, equality). |
| 1575 | string_t param(token + 1, token_len - 1); |
| 1576 | switch (traits::to_wchar(*token)) { |
| 1577 | case L'+': |
| 1578 | percent_decode(param); |
| 1579 | diffs.push_back(Diff(INSERT, param)); |
| 1580 | break; |
| 1581 | case L'-': |
| 1582 | // Fall through. |
| 1583 | case L'=': { |
| 1584 | ssize_t n; |
| 1585 | n = to_int(param); |
| 1586 | if (n < 0) { |
| 1587 | throw string_t(traits::cs(L"Negative number in diff_fromDelta: ") + param); |
| 1588 | } |
| 1589 | string_t text; |
| 1590 | text = safeMid(text1, pointer, n); |
| 1591 | pointer += n; |
| 1592 | if (traits::to_wchar(*token) == L'=') { |
| 1593 | diffs.push_back(Diff(EQUAL, text)); |
| 1594 | } else { |
| 1595 | diffs.push_back(Diff(DELETE, text)); |
| 1596 | } |
| 1597 | break; |
| 1598 | } |
| 1599 | default: |
| 1600 | throw string_t(string_t(traits::cs(L"Invalid diff operation in diff_fromDelta: ")) + *token); |
| 1601 | } |
| 1602 | } |
| 1603 | if (pointer != text1.length()) { |
| 1604 | throw string_t(traits::cs(L"Delta length (") + to_string(pointer) |
| 1605 | + traits::cs(L") smaller than source text length (") |
| 1606 | + to_string(text1.length()) + traits::from_wchar(L')')); |
| 1607 | } |
| 1608 | return diffs; |
| 1609 | } |
| 1610 | |
| 1611 | |
| 1612 | // MATCH FUNCTIONS |