Fossil SCM

Fix handling of backslash and tab in quoted JSON text for the --json option.

drh 2021-08-30 16:40 diff-color-enhancements
Commit 9a30e83d88d7ab4cd51a5a8fddc994be06f537df1735e39208815edaccfd092e
1 file changed +98 -34
+98 -34
--- src/diff.c
+++ src/diff.c
@@ -1722,62 +1722,126 @@
17221722
p->pOut = pOut;
17231723
return p;
17241724
}
17251725
17261726
/************************* DiffBuilderJson ********************************/
1727
+
1728
+/* Convert raw text into content suitable for a JSON string. Escape
1729
+** charaters that are special to HTML and to JSON:
1730
+**
1731
+** < -> &lt;
1732
+** > -> &gt;
1733
+** & -> &amp;
1734
+** " -> &quot;
1735
+** ' -> &#39;
1736
+** \ -> &#92;
1737
+**
1738
+** In addition, TAB characters are converted into an appropriate number
1739
+** of spaces. The *piCol value is the number of prior columns in the
1740
+** current line. Update the column count before returning, so that
1741
+** subsequent invocations can figure out the right number of spaces to
1742
+** insert for each tab.
1743
+*/
1744
+static void jsonize_to_blob(Blob *p, const char *zIn, int n, int *piCol){
1745
+ int c, i, x;
1746
+ int iCol = *piCol;
1747
+ for(i=0; i<n; i++){
1748
+ c = zIn[i];
1749
+ switch( c ){
1750
+ case '<':
1751
+ blob_append(p, "&lt;", 4);
1752
+ iCol++;
1753
+ break;
1754
+ case '>':
1755
+ blob_append(p, "&gt;", 4);
1756
+ iCol++;
1757
+ break;
1758
+ case '&':
1759
+ blob_append(p, "&amp;", 5);
1760
+ iCol++;
1761
+ break;
1762
+ case '"':
1763
+ blob_append(p, "&quot;", 6);
1764
+ iCol++;
1765
+ break;
1766
+ case '\'':
1767
+ blob_append(p, "&#39;", 5);
1768
+ iCol++;
1769
+ break;
1770
+ case '\\':
1771
+ blob_append(p, "&#92;", 5);
1772
+ iCol++;
1773
+ break;
1774
+ case '\t':
1775
+ x = 1 + (iCol+7)%8;
1776
+ blob_appendf(p, "%*s", x, "");
1777
+ iCol += x;
1778
+ break;
1779
+ default:
1780
+ blob_append_char(p, c);
1781
+ if( (c&0xc0)!=0x80 ) iCol++;
1782
+ break;
1783
+ }
1784
+ }
1785
+ *piCol = iCol;
1786
+}
17271787
static void dfjsonSkip(DiffBuilder *p, unsigned int n){
17281788
blob_appendf(p->pOut, "1,%u,\n", n);
17291789
}
17301790
static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){
1791
+ int iCol = 0;
17311792
blob_append(p->pOut, "2,\"",3);
1732
- htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1793
+ jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
17331794
blob_append(p->pOut, "\",\n",3);
17341795
}
17351796
static void dfjsonInsert(DiffBuilder *p, const DLine *pLine){
1797
+ int iCol = 0;
17361798
blob_append(p->pOut, "3,\"",3);
1737
- htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1799
+ jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
17381800
blob_append(p->pOut, "\",\n",3);
17391801
}
17401802
static void dfjsonDelete(DiffBuilder *p, const DLine *pLine){
1803
+ int iCol = 0;
17411804
blob_append(p->pOut, "4,\"",3);
1742
- htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1805
+ jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
17431806
blob_append(p->pOut, "\",\n",3);
17441807
}
17451808
static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
17461809
int i;
17471810
int x;
1748
- ChangeSpan span;
1749
- oneLineChange(pX, pY, &span);
1750
- blob_appendf(p->pOut, "5,\"");
1751
- for(i=x=0; i<span.n; i++){
1752
- int ofst = span.a[i].iStart1;
1753
- int len = span.a[i].iLen1;
1754
- if( len ){
1755
- htmlize_to_blob(p->pOut, pX->z+x, ofst - x);
1756
- x += ofst;
1757
- blob_append(p->pOut, "<mark>", 6);
1758
- htmlize_to_blob(p->pOut, pX->z+x, len);
1759
- x += len;
1760
- blob_append(p->pOut, "</mark>", 7);
1761
- }
1762
- }
1763
- if( x<pX->n ) htmlize_to_blob(p->pOut, pX->z+x, pX->n - x);
1764
- blob_append(p->pOut, "\",\n \"", -1);
1765
- for(i=x=0; i<span.n; i++){
1766
- int ofst = span.a[i].iStart2;
1767
- int len = span.a[i].iLen2;
1768
- if( len ){
1769
- htmlize_to_blob(p->pOut, pY->z+x, ofst - x);
1770
- x += ofst;
1771
- blob_append(p->pOut, "<mark>", 6);
1772
- htmlize_to_blob(p->pOut, pY->z+x, len);
1773
- x += len;
1774
- blob_append(p->pOut, "</mark>", 7);
1775
- }
1776
- }
1777
- if( x<pY->n ) htmlize_to_blob(p->pOut, pY->z+x, pY->n - x);
1778
- blob_append(p->pOut, "\"\n,", -1);
1811
+ int iCol;
1812
+ ChangeSpan span;
1813
+ oneLineChange(pX, pY, &span);
1814
+ blob_appendf(p->pOut, "5,\"");
1815
+ for(i=x=iCol=0; i<span.n; i++){
1816
+ int ofst = span.a[i].iStart1;
1817
+ int len = span.a[i].iLen1;
1818
+ if( len ){
1819
+ jsonize_to_blob(p->pOut, pX->z+x, ofst - x, &iCol);
1820
+ x += ofst;
1821
+ blob_append(p->pOut, "<mark>", 6);
1822
+ jsonize_to_blob(p->pOut, pX->z+x, len, &iCol);
1823
+ x += len;
1824
+ blob_append(p->pOut, "</mark>", 7);
1825
+ }
1826
+ }
1827
+ if( x<pX->n ) jsonize_to_blob(p->pOut, pX->z+x, pX->n - x, &iCol);
1828
+ blob_append(p->pOut, "\",\n \"", -1);
1829
+ for(i=x=iCol=0; i<span.n; i++){
1830
+ int ofst = span.a[i].iStart2;
1831
+ int len = span.a[i].iLen2;
1832
+ if( len ){
1833
+ jsonize_to_blob(p->pOut, pY->z+x, ofst - x, &iCol);
1834
+ x += ofst;
1835
+ blob_append(p->pOut, "<mark>", 6);
1836
+ jsonize_to_blob(p->pOut, pY->z+x, len, &iCol);
1837
+ x += len;
1838
+ blob_append(p->pOut, "</mark>", 7);
1839
+ }
1840
+ }
1841
+ if( x<pY->n ) jsonize_to_blob(p->pOut, pY->z+x, pY->n - x, &iCol);
1842
+ blob_append(p->pOut, "\",\n", -1);
17791843
}
17801844
static void dfjsonEnd(DiffBuilder *p){
17811845
blob_append(p->pOut, "0]", 2);
17821846
fossil_free(p);
17831847
}
17841848
--- src/diff.c
+++ src/diff.c
@@ -1722,62 +1722,126 @@
1722 p->pOut = pOut;
1723 return p;
1724 }
1725
1726 /************************* DiffBuilderJson ********************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1727 static void dfjsonSkip(DiffBuilder *p, unsigned int n){
1728 blob_appendf(p->pOut, "1,%u,\n", n);
1729 }
1730 static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){
 
1731 blob_append(p->pOut, "2,\"",3);
1732 htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1733 blob_append(p->pOut, "\",\n",3);
1734 }
1735 static void dfjsonInsert(DiffBuilder *p, const DLine *pLine){
 
1736 blob_append(p->pOut, "3,\"",3);
1737 htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1738 blob_append(p->pOut, "\",\n",3);
1739 }
1740 static void dfjsonDelete(DiffBuilder *p, const DLine *pLine){
 
1741 blob_append(p->pOut, "4,\"",3);
1742 htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n);
1743 blob_append(p->pOut, "\",\n",3);
1744 }
1745 static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1746 int i;
1747 int x;
1748 ChangeSpan span;
1749 oneLineChange(pX, pY, &span);
1750 blob_appendf(p->pOut, "5,\"");
1751 for(i=x=0; i<span.n; i++){
1752 int ofst = span.a[i].iStart1;
1753 int len = span.a[i].iLen1;
1754 if( len ){
1755 htmlize_to_blob(p->pOut, pX->z+x, ofst - x);
1756 x += ofst;
1757 blob_append(p->pOut, "<mark>", 6);
1758 htmlize_to_blob(p->pOut, pX->z+x, len);
1759 x += len;
1760 blob_append(p->pOut, "</mark>", 7);
1761 }
1762 }
1763 if( x<pX->n ) htmlize_to_blob(p->pOut, pX->z+x, pX->n - x);
1764 blob_append(p->pOut, "\",\n \"", -1);
1765 for(i=x=0; i<span.n; i++){
1766 int ofst = span.a[i].iStart2;
1767 int len = span.a[i].iLen2;
1768 if( len ){
1769 htmlize_to_blob(p->pOut, pY->z+x, ofst - x);
1770 x += ofst;
1771 blob_append(p->pOut, "<mark>", 6);
1772 htmlize_to_blob(p->pOut, pY->z+x, len);
1773 x += len;
1774 blob_append(p->pOut, "</mark>", 7);
1775 }
1776 }
1777 if( x<pY->n ) htmlize_to_blob(p->pOut, pY->z+x, pY->n - x);
1778 blob_append(p->pOut, "\"\n,", -1);
 
1779 }
1780 static void dfjsonEnd(DiffBuilder *p){
1781 blob_append(p->pOut, "0]", 2);
1782 fossil_free(p);
1783 }
1784
--- src/diff.c
+++ src/diff.c
@@ -1722,62 +1722,126 @@
1722 p->pOut = pOut;
1723 return p;
1724 }
1725
1726 /************************* DiffBuilderJson ********************************/
1727
1728 /* Convert raw text into content suitable for a JSON string. Escape
1729 ** charaters that are special to HTML and to JSON:
1730 **
1731 ** < -> &lt;
1732 ** > -> &gt;
1733 ** & -> &amp;
1734 ** " -> &quot;
1735 ** ' -> &#39;
1736 ** \ -> &#92;
1737 **
1738 ** In addition, TAB characters are converted into an appropriate number
1739 ** of spaces. The *piCol value is the number of prior columns in the
1740 ** current line. Update the column count before returning, so that
1741 ** subsequent invocations can figure out the right number of spaces to
1742 ** insert for each tab.
1743 */
1744 static void jsonize_to_blob(Blob *p, const char *zIn, int n, int *piCol){
1745 int c, i, x;
1746 int iCol = *piCol;
1747 for(i=0; i<n; i++){
1748 c = zIn[i];
1749 switch( c ){
1750 case '<':
1751 blob_append(p, "&lt;", 4);
1752 iCol++;
1753 break;
1754 case '>':
1755 blob_append(p, "&gt;", 4);
1756 iCol++;
1757 break;
1758 case '&':
1759 blob_append(p, "&amp;", 5);
1760 iCol++;
1761 break;
1762 case '"':
1763 blob_append(p, "&quot;", 6);
1764 iCol++;
1765 break;
1766 case '\'':
1767 blob_append(p, "&#39;", 5);
1768 iCol++;
1769 break;
1770 case '\\':
1771 blob_append(p, "&#92;", 5);
1772 iCol++;
1773 break;
1774 case '\t':
1775 x = 1 + (iCol+7)%8;
1776 blob_appendf(p, "%*s", x, "");
1777 iCol += x;
1778 break;
1779 default:
1780 blob_append_char(p, c);
1781 if( (c&0xc0)!=0x80 ) iCol++;
1782 break;
1783 }
1784 }
1785 *piCol = iCol;
1786 }
1787 static void dfjsonSkip(DiffBuilder *p, unsigned int n){
1788 blob_appendf(p->pOut, "1,%u,\n", n);
1789 }
1790 static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){
1791 int iCol = 0;
1792 blob_append(p->pOut, "2,\"",3);
1793 jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
1794 blob_append(p->pOut, "\",\n",3);
1795 }
1796 static void dfjsonInsert(DiffBuilder *p, const DLine *pLine){
1797 int iCol = 0;
1798 blob_append(p->pOut, "3,\"",3);
1799 jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
1800 blob_append(p->pOut, "\",\n",3);
1801 }
1802 static void dfjsonDelete(DiffBuilder *p, const DLine *pLine){
1803 int iCol = 0;
1804 blob_append(p->pOut, "4,\"",3);
1805 jsonize_to_blob(p->pOut, pLine->z, (int)pLine->n, &iCol);
1806 blob_append(p->pOut, "\",\n",3);
1807 }
1808 static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1809 int i;
1810 int x;
1811 int iCol;
1812 ChangeSpan span;
1813 oneLineChange(pX, pY, &span);
1814 blob_appendf(p->pOut, "5,\"");
1815 for(i=x=iCol=0; i<span.n; i++){
1816 int ofst = span.a[i].iStart1;
1817 int len = span.a[i].iLen1;
1818 if( len ){
1819 jsonize_to_blob(p->pOut, pX->z+x, ofst - x, &iCol);
1820 x += ofst;
1821 blob_append(p->pOut, "<mark>", 6);
1822 jsonize_to_blob(p->pOut, pX->z+x, len, &iCol);
1823 x += len;
1824 blob_append(p->pOut, "</mark>", 7);
1825 }
1826 }
1827 if( x<pX->n ) jsonize_to_blob(p->pOut, pX->z+x, pX->n - x, &iCol);
1828 blob_append(p->pOut, "\",\n \"", -1);
1829 for(i=x=iCol=0; i<span.n; i++){
1830 int ofst = span.a[i].iStart2;
1831 int len = span.a[i].iLen2;
1832 if( len ){
1833 jsonize_to_blob(p->pOut, pY->z+x, ofst - x, &iCol);
1834 x += ofst;
1835 blob_append(p->pOut, "<mark>", 6);
1836 jsonize_to_blob(p->pOut, pY->z+x, len, &iCol);
1837 x += len;
1838 blob_append(p->pOut, "</mark>", 7);
1839 }
1840 }
1841 if( x<pY->n ) jsonize_to_blob(p->pOut, pY->z+x, pY->n - x, &iCol);
1842 blob_append(p->pOut, "\",\n", -1);
1843 }
1844 static void dfjsonEnd(DiffBuilder *p){
1845 blob_append(p->pOut, "0]", 2);
1846 fossil_free(p);
1847 }
1848

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button