package net.lshift.spki;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;

/**
 * Pretty-print an SPKI S-expression.
 */
public class PrettyPrinter {
    public static void prettyPrint(PrintStream ps, SpkiInputStream stream)
        throws IOException,
            ParseException
    {
        int indent = 0;
        for (;;) {
            switch (stream.next()) {
            case ATOM:
                printPrefix(ps, indent);
                byte[] bytes = stream.atomBytes();
                boolean text = (bytes.length > 0);
                for (int i = 0; text && i < bytes.length; i++) {
                    if (bytes[i] < 0x20 || bytes[i] >= 0x7f
                            || bytes[i] == Constants.DOUBLEQUOTE
                            || bytes[i] == Constants.BACKSLASH)
                        text = false;
                }
                if (text) {
                    ps.print("\"");
                    ps.write(bytes);
                    ps.println("\"");
                } else if (bytes.length < 10) {
                    ps.print("#");
                    ps.write(Hex.encode(bytes));
                    ps.println("#");
                } else {
                    ps.print("|");
                    ps.write(Base64.encode(bytes));
                    ps.println("|");
                }
                break;
            case CLOSEPAREN:
                if (indent == 0) {
                    throw new ParseException("Too many closeparens");
                }
                indent -= 1;
                printPrefix(ps, indent);
                ps.println(")");
                break;
            case OPENPAREN:
                printPrefix(ps, indent);
                ps.println("(");
                indent += 1;
                break;
            case EOF:
                return;
            }
        }
    }

    private static void printPrefix(PrintStream ps, int indent)
    {
        for (int i = 0; i < indent; i++) {
            ps.print("    ");
        }
    }

    public static String prettyPrint(
        CanonicalSpkiInputStream stream) throws ParseException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            prettyPrint(new PrintStream(baos), stream);
        } catch (IOException e) {
            // should not be possible
            throw new RuntimeException(e);
        }
        return new String(baos.toByteArray(), Constants.ASCII);
    }

}

@@ -114,16 +114,67 @@
 tream;%0A%0A
+import net.lshift.spki.SpkiInputStream.TokenType;%0A%0A
 import o
@@ -211,16 +211,16 @@
 Base64;%0A
-
 import o
@@ -630,878 +630,43 @@
     
-byte%5B%5D bytes = stream.atomBytes();%0A                boolean text = (bytes.length %3E 0);%0A                for (int i = 0; text && i %3C bytes.length; i++) %7B%0A                    if (bytes%5Bi%5D %3C 0x20 %7C%7C bytes%5Bi%5D %3E= 0x7f%0A                            %7C%7C bytes%5Bi%5D == Constants.DOUBLEQUOTE%0A                            %7C%7C bytes%5Bi%5D == Constants.BACKSLASH)%0A                        text = false;%0A                %7D%0A                if (text) %7B%0A                    ps.print(%22%5C%22%22);%0A                    ps.write(bytes);%0A                    ps.println(%22%5C%22%22);%0A                %7D else if (bytes.length %3C 10) %7B%0A                    ps.print(%22#%22);%0A                    ps.write(Hex.encode(bytes));%0A                    ps.println(%22#%22);%0A                %7D else %7B%0A                    ps.print(%22%7C%22);%0A                    ps.write(Base64.encode(bytes));%0A                    ps.println(%22%7C%22);%0A                %7D
+printBytes(ps, stream.atomBytes());
 %0A   
@@ -1060,17 +1060,122 @@
 rint
-ln
 (%22(%22);%0A
+                stream.nextAssertType(TokenType.ATOM);%0A                printBytes(ps, stream.atomBytes());%0A
     
@@ -1408,24 +1408,24 @@
 ent; i++) %7B%0A
-
             
@@ -1455,24 +1455,805 @@
    %7D%0A    %7D%0A%0A
+    private static void printBytes(PrintStream ps, byte%5B%5D bytes)%0A        throws IOException%0A    %7B%0A        boolean text = (bytes.length %3E 0);%0A        for (int i = 0; text && i %3C bytes.length; i++) %7B%0A            if (bytes%5Bi%5D %3C 0x20 %7C%7C bytes%5Bi%5D %3E= 0x7f%0A                    %7C%7C bytes%5Bi%5D == Constants.DOUBLEQUOTE%0A                    %7C%7C bytes%5Bi%5D == Constants.BACKSLASH)%0A                text = false;%0A        %7D%0A        if (text) %7B%0A            ps.print(%22%5C%22%22);%0A            ps.write(bytes);%0A            ps.println(%22%5C%22%22);%0A        %7D else if (bytes.length %3C 10) %7B%0A            ps.print(%22#%22);%0A            ps.write(Hex.encode(bytes));%0A            ps.println(%22#%22);%0A        %7D else %7B%0A            ps.print(%22%7C%22);%0A            ps.write(Base64.encode(bytes));%0A            ps.println(%22%7C%22);%0A        %7D%0A    %7D%0A%0A
     public s

Make new pretty output compact the way the old was.