Subversion Repositories display

Rev

Rev 548 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2007 Steve Ratcliffe
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program 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.
 *
 *
 * Author: Steve Ratcliffe
 * Create date: Dec 16, 2007
 */

package test.display;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * An item to display.  By item we mean a byte,int,string or arbitary length
 * set of bytes.  The address of the object will be printed on the left, a hex
 * dump will be in the middle and comments will be on the right.
 *
 * You can add any number of comments, they will be printed on separate lines, in
 * the right column.
 *
 * The general look of the output is similar to imgdecode by John Mechalas.
 *
 * @author Steve Ratcliffe
 */

public class DisplayItem {
        private long startPos;

        private byte[] bytes;
        private int value;
        private int nbytes;

        private final List<String> texts = new ArrayList<>();
        private int bytelines;
        private long sectStart;

        public void setStartPos(long startPos) {
                this.startPos = startPos;
        }

        /**
         * If this is set, then you also get another column with offsets into the
         * section.  This is in addition to the offsets into the file.
         *
         * @param sectStart The start offset of the section with respect to the
         * beginning of the (sub)-file.  (ie. NOT absolute in the .img file).
         */

        void setSectStart(long sectStart) {
                this.sectStart = sectStart;
        }

        public int setBytes4(int in) {
                value = in;
                setBytes(in, 4);
                return in;
        }

        public int setBytes3(int in) {
                value = in;
                setBytes(in, 3);
                return in;
        }

        public int setBytes2(int in) {
                value = in;
                setBytes(in, 2);
                return in;
        }

        public int setBytes1(int in) {
                value = in;
                setBytes(in, 1);
                return in;
        }

        public int getValue() {
                return value;
        }

        private void setBytes(int in, int n) {
                byte[] newbytes = new byte[nbytes + n];

                if (bytes != null)
                        System.arraycopy(bytes, 0, newbytes, 0, bytes.length);

                bytes = newbytes;
                for (int i = 0; i < n; i++) {
                        bytes[nbytes+i] = (byte) (in >> (i) * 8 & 0xff);
                }
                nbytes += n;
        }

        public void print(PrintStream out) {
                bytelines = (nbytes + 7) / 8 ;
                int nlines = Math.max(bytelines, getTextLines());
                StringBuilder sb = new StringBuilder(128);
                long pos = startPos;

                for (int i = 0; i < nlines; i++, pos+=8) {
                        if (pos >= startPos + nbytes)
                                sb.append("         | ");
                        else {
//                              out.format("%08x | ", pos);
                                // much faster:
                                final String s = Long.toHexString(pos);
                                int padding = 8 - s.length();
                                if (padding > 0)
                                        sb.append("00000000".substring(0, padding));
                                sb.append(s).append(" | ");
                        }
                        printSectOff(sb, pos);
                        printBytes(sb, i);
                        printLines(sb, i);
                        out.println(sb.toString());
                        sb.setLength(0);
                }
        }

        private void printSectOff(StringBuilder sb, long pos) {
                if (sectStart == 0)
                        return;
                if (pos >= startPos + nbytes) {
                        sb.append("       | ");
                } else {
                        final String s = Long.toHexString(pos - sectStart);
                        int padding = 6 - s.length();
                        if (padding > 0)
                                sb.append("00000000".substring(0, padding));
                        sb.append(s).append(" | ");
                }
        }

        private void printLines(StringBuilder sb, int lineno) {
                if (lineno >= getTextLines())
                        return;

                String s = texts.get(lineno);
                if (s != null)
                        sb.append(s);
        }

        private void printBytes(StringBuilder sb, int lineno) {
                int pos = lineno * 8;
                for (int i = 0; i < 8; i++, pos++) {
                        if (lineno >= bytelines || (8*lineno + i) >= nbytes) {
                                sb.append("   ");
                        } else {
                                String s = Integer.toHexString(bytes[pos] & 0xff);
                                if (s.length() < 2)
                                        sb.append('0');
                                sb.append(s).append(' ');
                        }
                }
                sb.append("| ");
        }

        public void addText(String text) {
                texts.add(text);
        }

        public DisplayItem addText(String s, Object ... val) {
                texts.add(String.format(Locale.ENGLISH, s, val));
                return this;
        }

        public byte[] setBytes(byte[] buf) {
                return setBytes(buf, buf.length);
        }

        protected byte[] setBytes(byte[] buf, int len) {
                assert this.bytes == null;
                this.bytes = buf;
                this.nbytes = len;
                return buf;
        }

        private int getTextLines() {
                return texts.size();
        }

        public byte[] getBytes() {
                return bytes;
        }
}