package yuku.alkitab.yes2.io; import yuku.alkitab.io.Utf8Decoder; import yuku.bintex.BintexReader; public interface Yes2VerseTextDecoder { String[] separateIntoVerses(BintexReader br, int verse_count, boolean lowercased) throws Exception; String makeIntoSingleString(BintexReader br, int verse_count, boolean lowercased) throws Exception; class Ascii implements Yes2VerseTextDecoder { final ThreadLocal<byte[]> verseBuf_ = new ThreadLocal<byte[]>() { @Override protected byte[] initialValue() { return new byte[4000]; } }; @Override public String[] separateIntoVerses(BintexReader br, int verse_count, boolean lowercased) throws Exception { byte[] verseBuf = verseBuf_.get(); String[] res = new String[verse_count]; for (int i = 0; i < verse_count; i++) { int verse_len = br.readVarUint(); br.readRaw(verseBuf, 0, verse_len); if (lowercased) { for (int j = 0; j < verse_len; j++) { byte b = verseBuf[j]; if (b <= (byte)'Z' && b >= (byte)'A') { verseBuf[i] |= 0x20; } } } //# WARNING: This will work only if all bytes are less than 0x80. @SuppressWarnings("deprecation") String verse = new String(verseBuf, 0, 0, verse_len); res[i] = verse; } return res; } /* (2017-01) Can be optimized, but we are moving away from ascii encoding. So probably it is not worth it to optimize this. */ @Override public String makeIntoSingleString(BintexReader br, int verse_count, boolean lowercased) throws Exception { StringBuilder sb = new StringBuilder(); String[] verses = separateIntoVerses(br, verse_count, lowercased); for (String verse: verses) { sb.append(verse).append('\n'); } return sb.toString(); } } class Utf8 implements Yes2VerseTextDecoder { final ThreadLocal<byte[]> verseBuf_ = new ThreadLocal<byte[]>() { @Override protected byte[] initialValue() { return new byte[4000]; } }; @Override public String[] separateIntoVerses(BintexReader br, int verse_count, boolean lowercased) throws Exception { byte[] verseBuf = verseBuf_.get(); String[] res = new String[verse_count]; for (int i = 0; i < verse_count; i++) { int verse_len = br.readVarUint(); if (verse_len > verseBuf.length) { verseBuf = new byte[verse_len + 1000]; verseBuf_.set(verseBuf); } br.readRaw(verseBuf, 0, verse_len); String verse; if (lowercased) { verse = Utf8Decoder.toStringLowerCase(verseBuf, 0, verse_len); } else { verse = Utf8Decoder.toString(verseBuf, 0, verse_len); } res[i] = verse; } return res; } @Override public String makeIntoSingleString(BintexReader br, int verse_count, boolean lowercased) throws Exception { return Utf8Decoder.toStringFromVersesWithPrependedLengths(br, verse_count, lowercased); } } }