java/ch/wlkl/wsh/Strings.java

package ch.wlkl.wsh;

import static ch.wlkl.wsh.Env.env;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Strings extends Top {
    
    final static Pattern oneWord = Pattern.compile("\\s*(\\S+)");
    final private static Matcher xQuoteMatcher = Pattern.compile("[^\"\\\\\n]+").matcher("");
    
    public static String unquote(String src) {
        if (src.length() == 0)
            return src;
        
        final char qu = src.charAt(0);
        String res = "";
        int ex, bx = 1;
        
        while (true) {
            ex = src.indexOf(qu, bx);    
            if (ex < 0)
                sFail("non terminated string: " + src);
            if (ex == src.length() - 1 )
                return res + src.substring(bx, ex);
            if (src.charAt(ex+1) != qu)
                sFail("single quote at position " + ex + " in string: " + src);
            res += src.substring(bx, ex) + qu;
            bx = ex+2;
        }
    }

    public static String quote(String src) {
        return quote(src, "\"");
    }
    public static String quote(String src, String q) {
        String res = q;
        if (src == null)
            return q + q;
        int fx = 0;
        int px;
        while(true) {
            px = src.indexOf(q, fx);
            if (px < 0)
                break;
            res += src.substring(fx, fx = q.length() + px) + q;
        }
        return res + src.substring(fx) + q;
    }

    public static String hex(CharSequence src) {
        StringBuffer b = new StringBuffer(2 * src.length());
        for (int ix=0; ix < src. length(); ix ++) {
            char c = src.charAt(ix);
            if (c < 256)
                b.append(String.format("%2h", c));
            else
                b.append("\\u(").append(String.format("%h", c)).append(')');            
        }
        return b.toString();
    }
    
    public static String xUnquote(String src) {
        if (src == null || src.length() <= 1)
            sFail("cannot unquote this string: <" + src + ">");
        
        StringBuffer buf = new StringBuffer("");
        final char qu = src.charAt(0);
        char c = 0;
        int sx = 1, qx = 0, bx = 0; 
        
        while (true) {
            if (qx < sx)
                if ((qx = src.indexOf(qu, sx)) < 0)
                    qx = src.length();
            if (bx < sx)
                if ((bx = src.indexOf('\\', sx)) < 0)
                    bx = src.length();
            if (bx < qx) {
                if (bx + 1>= src.length())
                    sFail("backslash at end of String: <" + src + ">");
                buf.append(src, sx, bx).append((c = src.charAt(bx+1)) == 'n' ? '\n' : c == 't' ? 't' : c);
                sx = bx+2;
            } else {
                if (qx + 1 == src.length())
                    return buf.append(src, sx, qx).toString();
                else
                    sFail("quote within String: <" + src + ">");
            }
        }
    }

    public static String xQuote(String src) {
        if (src == null)
            return "\"\"";
        StringBuffer buf = new StringBuffer("\"");
        int nx = 0;
        xQuoteMatcher.reset(src);
        while (true) {
            if (xQuoteMatcher.lookingAt()) {
                buf.append(xQuoteMatcher.group());
                nx = xQuoteMatcher.end();
            } 
            if (nx >= src.length())
                return buf.append('"').toString();
            buf.append('\\').append(src.charAt(nx) == '\n' ? 'n' : src.charAt(nx));
            xQuoteMatcher.region(++nx, src.length());
        }
    }

    public static String fill(String rep, int len) {
        StringBuffer b = new StringBuffer(rep == null || rep.equals("") ? " " : rep);
        while (b.length() < len)
            b.append(b);
        return b.substring(0, len);
    }


    public static String cut(String src, int len, String rep) {
        int l = src.length();
        return l == len ? src : l < len ? src + fill(rep, len - l) : src.substring(0, len); 
    }
    
    public static String cat(Collection<String> lst, String le, String mi, String ri) {
        StringBuffer b = new StringBuffer(le);
        boolean first = true;
        for (String s : lst) {
            if (first)
                first = false;
            else
                b.append(mi);
            b.append(s);
        }
        return b.append(ri).toString();
    }

    public static String cat(Collection<String> lst, String mi) {
        return cat(lst, "", mi, "");
    }

    public static void words() {
        Matcher match = oneWord.matcher("");
        String one;
        while (null != (one = env().read())) {
            match.reset(one);
            while (match.lookingAt()) {
                env().write(match.group(1));
                match.region(match.end(), one.length());
            } 
        }
    } 

    public static void wc(boolean wrLines) {
        Matcher match = oneWord.matcher("");
        String one;
        int lc = 0, wc = 0, cc = 0;
        while (null != (one = env().read())) {
            lc ++;
            cc += one.length();
            
            match.reset(one);
            while (match.lookingAt()) {
                wc++;
                match.region(match.end(), one.length());
            } 
            if (wrLines)
                env().write(one);
        }
        env().write("counted " + lc + " lines, " + wc + " words, " + cc + " chars");
    } 
}