001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.survival.data;
022
023import java.io.Serializable;
024import java.io.UnsupportedEncodingException;
025
026/**
027 *http://www.javamex.com/tutorials/memory/ascii_charsequence.shtml
028 * @author Scooter Willis <willishf at gmail dot com>
029 */
030public class CompactCharSequence implements CharSequence, Serializable {
031
032        static final long serialVersionUID = 1L;
033        private static final String ENCODING = "ISO-8859-1";
034        private final int offset;
035        private final int end;
036        private final byte[] data;
037        private final boolean nullstring;
038
039        private CompactCharSequence(byte[] data, int offset, int end) {
040                this.data = data;
041                this.offset = offset;
042                this.end = end;
043                nullstring = false;
044        }
045
046        /**
047         *
048         * @param str
049         */
050        public CompactCharSequence(String str) {
051                try {
052                        if (str != null) {
053                                data = str.getBytes(ENCODING);
054                                offset = 0;
055                                end = data.length;
056                                nullstring = false;
057                        } else {
058                                data = new byte[0];
059                                offset = 0;
060                                end = 0;
061                                nullstring = true;
062                        }
063                } catch (UnsupportedEncodingException e) {
064                        throw new RuntimeException("Unexpected: " + ENCODING + " not supported!");
065                }
066        }
067
068        @Override
069        public char charAt(int index) {
070                int ix = index + offset;
071                if (ix >= end) {
072                        throw new StringIndexOutOfBoundsException("Invalid index "
073                                        + index + " length " + length());
074                }
075                return (char) (data[ix] & 0xff);
076        }
077
078        @Override
079        public int length() {
080                return end - offset;
081        }
082
083        @Override
084        public CharSequence subSequence(int start, int end) {
085                if (start < 0 || end >= (this.end - offset)) {
086                        throw new IllegalArgumentException("Illegal range "
087                                        + start + "-" + end + " for sequence of length " + length());
088                }
089                return new CompactCharSequence(data, start + offset, end + offset);
090        }
091
092        @Override
093        public String toString() {
094                try {
095                        if (nullstring) {
096                                return null;
097                        } else {
098                                if(length() == 0)
099                                        return "";
100                                else
101                                        return new String(data, offset, end - offset, ENCODING);
102                        }
103                } catch (UnsupportedEncodingException e) {
104                        throw new RuntimeException("Unexpected: " + ENCODING + " not supported");
105                }
106        }
107}