| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-11 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - struct TextDiffHelpers
 - {
 -     enum { minLengthToMatch = 3 };
 - 
 -     struct StringRegion
 -     {
 -         StringRegion (const String& s) noexcept
 -             : text (s.getCharPointer()), start (0), length (s.length()) {}
 - 
 -         StringRegion (const String::CharPointerType& t, int s, int len)  noexcept
 -             : text (t), start (s), length (len) {}
 - 
 -         String::CharPointerType text;
 -         int start, length;
 -     };
 - 
 -     static void addInsertion (TextDiff& td, const String::CharPointerType& text, int index, int length)
 -     {
 -         TextDiff::Change c;
 -         c.insertedText = String (text, (size_t) length);
 -         c.start = index;
 -         c.length = length;
 -         td.changes.add (c);
 -     }
 - 
 -     static void addDeletion (TextDiff& td, int index, int length)
 -     {
 -         TextDiff::Change c;
 -         c.start = index;
 -         c.length = length;
 -         td.changes.add (c);
 -     }
 - 
 -     static void diffSkippingCommonStart (TextDiff& td, const StringRegion& a, const StringRegion& b)
 -     {
 -         String::CharPointerType sa (a.text);
 -         String::CharPointerType sb (b.text);
 -         const int maxLen = jmax (a.length, b.length);
 - 
 -         for (int i = 0; i < maxLen; ++i, ++sa, ++sb)
 -         {
 -             if (*sa != *sb)
 -             {
 -                 diffRecursively (td, StringRegion (sa, a.start + i, a.length - i),
 -                                      StringRegion (sb, b.start + i, b.length - i));
 -                 break;
 -             }
 -         }
 -     }
 - 
 -     static void diffRecursively (TextDiff& td, const StringRegion& a, const StringRegion& b)
 -     {
 -         int indexA, indexB;
 -         const int len = findLongestCommonSubstring (a.text, a.length,
 -                                                     b.text, b.length,
 -                                                     indexA, indexB);
 - 
 -         if (len >= minLengthToMatch)
 -         {
 -             jassert (indexA >= 0 && indexA <= a.length);
 -             jassert (indexB >= 0 && indexB <= b.length);
 -             jassert (String (a.text + indexA, (size_t) len) == String (b.text + indexB, (size_t) len));
 - 
 -             if (indexA > 0 && indexB > 0)
 -                 diffSkippingCommonStart (td, StringRegion (a.text, a.start, indexA),
 -                                              StringRegion (b.text, b.start, indexB));
 -             else if (indexA > 0)
 -                 addDeletion (td, b.start, indexA);
 -             else if (indexB > 0)
 -                 addInsertion (td, b.text, b.start, indexB);
 - 
 -             diffRecursively (td, StringRegion (a.text + indexA + len, a.start + indexA + len, a.length - indexA - len),
 -                                  StringRegion (b.text + indexB + len, b.start + indexB + len, b.length - indexB - len));
 -         }
 -         else
 -         {
 -             if (a.length > 0)   addDeletion (td, b.start, a.length);
 -             if (b.length > 0)   addInsertion (td, b.text, b.start, b.length);
 -         }
 -     }
 - 
 -     static int findLongestCommonSubstring (String::CharPointerType a, const int lenA,
 -                                            const String::CharPointerType& b, const int lenB,
 -                                            int& indexInA, int& indexInB)
 -     {
 -         if (lenA == 0 || lenB == 0)
 -             return 0;
 - 
 -         HeapBlock<int> lines;
 -         lines.calloc (2 + 2 * (size_t) lenB);
 - 
 -         int* l0 = lines;
 -         int* l1 = l0 + lenB + 1;
 - 
 -         int bestLength = 0;
 -         indexInA = indexInB = 0;
 - 
 -         for (int i = 0; i < lenA; ++i)
 -         {
 -             const juce_wchar ca = a.getAndAdvance();
 -             String::CharPointerType b2 (b);
 - 
 -             for (int j = 0; j < lenB; ++j)
 -             {
 -                 if (ca != b2.getAndAdvance())
 -                 {
 -                     l1[j + 1] = 0;
 -                 }
 -                 else
 -                 {
 -                     const int len = l0[j] + 1;
 -                     l1[j + 1] = len;
 - 
 -                     if (len > bestLength)
 -                     {
 -                         bestLength = len;
 -                         indexInA = i;
 -                         indexInB = j;
 -                     }
 -                 }
 -             }
 - 
 -             std::swap (l0, l1);
 -         }
 - 
 -         indexInA -= bestLength - 1;
 -         indexInB -= bestLength - 1;
 -         return bestLength;
 -     }
 - };
 - 
 - TextDiff::TextDiff (const String& original, const String& target)
 - {
 -     TextDiffHelpers::diffSkippingCommonStart (*this, original, target);
 - }
 - 
 - String TextDiff::appliedTo (String text) const
 - {
 -     for (int i = 0; i < changes.size(); ++i)
 -         text = changes.getReference(i).appliedTo (text);
 - 
 -     return text;
 - }
 - 
 - bool TextDiff::Change::isDeletion() const noexcept
 - {
 -     return insertedText.isEmpty();
 - }
 - 
 - String TextDiff::Change::appliedTo (const String& text) const noexcept
 - {
 -     return text.substring (0, start) + (isDeletion() ? text.substring (start + length)
 -                                                      : (insertedText + text.substring (start)));
 - }
 - 
 - //==============================================================================
 - //==============================================================================
 - #if JUCE_UNIT_TESTS
 - 
 - class DiffTests  : public UnitTest
 - {
 - public:
 -     DiffTests() : UnitTest ("TextDiff class") {}
 - 
 -     static String createString()
 -     {
 -         juce_wchar buffer[50] = { 0 };
 -         Random r;
 - 
 -         for (int i = r.nextInt (49); --i >= 0;)
 -         {
 -             if (r.nextInt (10) == 0)
 -             {
 -                 do
 -                 {
 -                     buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
 -                 }
 -                 while (! CharPointer_UTF16::canRepresent (buffer[i]));
 -             }
 -             else
 -                 buffer[i] = (juce_wchar) ('a' + r.nextInt (3));
 -         }
 - 
 -         return CharPointer_UTF32 (buffer);
 -     }
 - 
 -     void testDiff (const String& a, const String& b)
 -     {
 -         TextDiff diff (a, b);
 -         const String result (diff.appliedTo (a));
 -         expectEquals (result, b);
 -     }
 - 
 -     void runTest()
 -     {
 -         beginTest ("TextDiff");
 - 
 -         testDiff (String::empty, String::empty);
 -         testDiff ("x", String::empty);
 -         testDiff (String::empty, "x");
 -         testDiff ("x", "x");
 -         testDiff ("x", "y");
 -         testDiff ("xxx", "x");
 -         testDiff ("x", "xxx");
 - 
 -         for (int i = 5000; --i >= 0;)
 -         {
 -             String s (createString());
 -             testDiff (s, createString());
 -             testDiff (s + createString(), s + createString());
 -         }
 -     }
 - };
 - 
 - static DiffTests diffTests;
 - 
 - #endif
 
 
  |