Changeset 493

Show
Ignore:
Timestamp:
11/18/07 19:51:21 (1 year ago)
Author:
andrei
Message:

Made std.string.munch more general and added function chompPrefix

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • candidate/phobos/std/string.d

    r394 r493  
    4040private import std.ctype; 
    4141private import std.stdarg; 
    42 import std.contracts
     42import std.contracts, std.typetuple, std.conv, std.traits
    4343 
    4444extern (C) 
     
    15401540} 
    15411541 
     1542/** 
     1543 * Returns $(D_PARAM true) if and only if the array $(D_PARAM longer) 
     1544 * starts with array $(D_PARAM shorter). 
     1545 */ 
     1546bool startsWith(A1, A2)(A1 longer, A2 shorter) 
     1547{ 
     1548    static if (is(typeof(longer[0 .. shorter.length] == shorter))) 
     1549    { 
     1550        // the easy way: arrays, directly comparable 
     1551        return longer.length >= shorter.length && 
     1552            longer[0 .. shorter.length] == shorter; 
     1553    } 
     1554    else 
     1555    { 
     1556        // different element types, etc. 
     1557        static if (isSomeString!(A1) && isSomeString!(A2)) 
     1558        { 
     1559            // UTF-informed comparison 
     1560            // find the largest character of the two 
     1561            static if (longer[0].sizeof > shorter[0].sizeof) 
     1562            { 
     1563                alias typeof(longer[0]) Char; 
     1564                if (shorter.length / Char.sizeof > longer.length) return false; 
     1565                size_t i = 0; 
     1566                foreach (Char c; shorter) 
     1567                { 
     1568                    if (i == longer.length || longer[i] != c) return false; 
     1569                    ++i; 
     1570                } 
     1571            } 
     1572            else 
     1573            { 
     1574                static assert(longer[0].sizeof < shorter[0].sizeof, 
     1575                    "Looks like there's a bug in the compiler"); 
     1576                alias typeof(shorter[0]) Char; 
     1577                if (shorter.length > longer.length) return false; 
     1578                size_t i = 0; 
     1579                foreach (Char c; longer) 
     1580                { 
     1581                    if (i == shorter.length) return true; 
     1582                    if (shorter[i] != c) return false; 
     1583                    ++i; 
     1584                } 
     1585            } 
     1586        } 
     1587        else 
     1588        { 
     1589            // raw element-by-element comparison 
     1590            if (longer.length < shorter.length) return false; 
     1591            foreach (i, e; shorter) 
     1592            { 
     1593                if (longer[i] != e) return false; 
     1594            } 
     1595        } 
     1596    } 
     1597    return true; 
     1598} 
     1599 
     1600unittest 
     1601{ 
     1602    alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]) 
     1603        StringTypes; 
     1604    alias TypeTuple!(ubyte[], int[], double[]) OtherTypes; 
     1605    foreach (T1 ; StringTypes) 
     1606    { 
     1607        foreach (T2 ; StringTypes) 
     1608        { 
     1609            foreach (T3 ; OtherTypes) 
     1610            { 
     1611                auto a = to!(T1)("abcde"), b = to!(T2)("abcdefgh"), 
     1612                    c = to!(T2)(""); 
     1613                auto d = to!(T3)([2, 3]); 
     1614                assert(startsWith(b, a)); 
     1615                assert(!startsWith(a, b)); 
     1616                assert(startsWith(b, c)); 
     1617                assert(startsWith(a, c)); 
     1618                assert(!startsWith(c, b)); 
     1619                assert(!startsWith(c, a)); 
     1620                assert(!startsWith(a, d)); 
     1621                assert(!startsWith(d, a)); 
     1622                assert(!startsWith(b, d)); 
     1623                assert(!startsWith(d, b)); 
     1624                assert(!startsWith(c, d)); 
     1625                assert(startsWith(d, c)); 
     1626            } 
     1627        } 
     1628    } 
     1629} 
     1630 
     1631/** 
     1632 * Returns $(D_PARAM true) if and only if the array $(D_PARAM longer) 
     1633 * ends with array $(D_PARAM shorter). 
     1634 */ 
     1635bool endsWith(A1, A2)(A1 longer, A2 shorter) 
     1636{ 
     1637    static if (is(typeof(longer[$ - shorter.length .. $] == shorter))) 
     1638    { 
     1639        // the easy way: arrays, directly comparable 
     1640        return longer.length >= shorter.length && 
     1641            longer[$ - shorter.length .. $] == shorter; 
     1642    } 
     1643    else 
     1644    { 
     1645        // different element types, etc. 
     1646        static if (isSomeString!(A1) && isSomeString!(A2)) 
     1647        { 
     1648            // UTF-informed comparison 
     1649            // find the largest character of the two 
     1650            static if (longer[0].sizeof > shorter[0].sizeof) 
     1651            { 
     1652                alias typeof(longer[0]) Char; 
     1653                if (shorter.length > longer.length * Char.sizeof) return false; 
     1654                size_t i = longer.length - 1; 
     1655                foreach_reverse (Char c; shorter) 
     1656                { 
     1657                    if (i == 0 || longer[i] != c) return false; 
     1658                    --i; 
     1659                } 
     1660            } 
     1661            else 
     1662            { 
     1663                static assert(longer[0].sizeof < shorter[0].sizeof, 
     1664                    "Looks like there's a bug in the compiler"); 
     1665                alias typeof(shorter[0]) Char; 
     1666                if (shorter.length > longer.length) return false; 
     1667                if (!shorter.length) return true; 
     1668                size_t i = shorter.length - 1; 
     1669                foreach_reverse (Char c; longer) 
     1670                { 
     1671                    if (i == 0) return true; 
     1672                    if (shorter[i] != c) return false; 
     1673                    --i; 
     1674                } 
     1675            } 
     1676        } 
     1677        else 
     1678        { 
     1679            // raw element-by-element comparison 
     1680            if (longer.length < shorter.length) return false; 
     1681            foreach (i, e; longer[$ - shorter.length .. $]) 
     1682            { 
     1683                if (longer[i] != e) return false; 
     1684            } 
     1685        } 
     1686    } 
     1687    return true; 
     1688} 
     1689 
     1690unittest 
     1691{ 
     1692    alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]) 
     1693        TestTypes; 
     1694    alias TypeTuple!(ubyte[], int[], double[]) OtherTypes; 
     1695    foreach (T1 ; TestTypes) 
     1696    { 
     1697        foreach (T2 ; TestTypes) 
     1698        { 
     1699            foreach (T3 ; OtherTypes) 
     1700            { 
     1701                auto a = to!(T1)("efgh"), b = to!(T2)("abcdefgh"), 
     1702                    c = to!(T2)(""), d = to!(T3)([1, 2]); 
     1703                assert(endsWith(b, a)); 
     1704                assert(!endsWith(a, b)); 
     1705                assert(endsWith(b, c)); 
     1706                assert(endsWith(a, c)); 
     1707                assert(!endsWith(c, b)); 
     1708                assert(!endsWith(c, a)); 
     1709                assert(!endsWith(a, d)); 
     1710                assert(!endsWith(d, a)); 
     1711                assert(!endsWith(b, d)); 
     1712                assert(!endsWith(d, b)); 
     1713                assert(!endsWith(c, d)); 
     1714                assert(endsWith(d, c)); 
     1715            } 
     1716        } 
     1717    } 
     1718} 
     1719 
    15421720/******************************************* 
    15431721 * Returns s[] sans trailing delimiter[], if any. 
     
    16091787} 
    16101788 
     1789/** 
     1790 * If $(D_PARAM longer.startsWith(shorter)), returns $(D_PARAM 
     1791 * longer[shorter.length .. $]). Otherwise, returns $(D_PARAM longer). 
     1792 */ 
     1793 
     1794C1[] chompPrefix(C1, C2)(C1[] longer, C2[] shorter) 
     1795{ 
     1796    return startsWith(longer, shorter) ? longer[shorter.length .. $] 
     1797        : longer; 
     1798} 
     1799 
     1800unittest 
     1801{ 
     1802    auto a = "abcde", b = "abcdefgh"; 
     1803    assert(chompPrefix(b, a) == "fgh"); 
     1804    assert(chompPrefix(a, b) == "abcde"); 
     1805} 
    16111806 
    16121807/*********************************************** 
     
    30193214 */ 
    30203215 
    3021 S munch(S)(ref S s, S pattern) 
     3216S1 munch(S1, S2)(ref S1 s, S2 pattern) 
    30223217{ 
    30233218    size_t j = s.length;