From 1c8a93bf9e0bac22ba14f3f50c1299e82f79b1e2 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 14 May 2024 01:42:22 +0000 Subject: [PATCH] Add support for surrogate pairs in text indexes (e.g. emoticons), fixes #157 git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1413 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 5 + .../jackcess/impl/General97IndexCodes.java | 2 +- .../impl/GeneralLegacyIndexCodes.java | 91 ++++++++++++++---- src/test/data/V2010/testEmoticonsV2010.accdb | Bin 0 -> 385024 bytes .../jackcess/TestUtil.java | 13 ++- .../jackcess/impl/IndexCodesTest.java | 12 ++- .../jackcess/impl/JetFormatTest.java | 3 +- 7 files changed, 101 insertions(+), 25 deletions(-) create mode 100755 src/test/data/V2010/testEmoticonsV2010.accdb diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3297bea..d6f54b0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -4,6 +4,11 @@ Tim McCune + + + Add support for surrogate pairs in text indexes (e.g. emoticons). + + Make NumberFormatter locale aware, using the currently configured diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/General97IndexCodes.java b/src/main/java/com/healthmarketscience/jackcess/impl/General97IndexCodes.java index 77ebb67..a988a03 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/General97IndexCodes.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/General97IndexCodes.java @@ -114,7 +114,7 @@ public class General97IndexCodes extends GeneralLegacyIndexCodes char c = str.charAt(i); CharHandler ch = getCharHandler(c); - byte[] bytes = ch.getInlineBytes(); + byte[] bytes = ch.getInlineBytes(c); if(bytes != null) { // write the "inline" codes immediately bout.write(bytes); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/GeneralLegacyIndexCodes.java b/src/main/java/com/healthmarketscience/jackcess/impl/GeneralLegacyIndexCodes.java index 0d151e0..df3a781 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/GeneralLegacyIndexCodes.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/GeneralLegacyIndexCodes.java @@ -103,6 +103,12 @@ public class GeneralLegacyIndexCodes { return parseSignificantCodes(codeStrings); } }, + SURROGATE("Q") { + @Override public CharHandler parseCodes(String[] codeStrings) { + // these are not parsed from the codes files + throw new UnsupportedOperationException(); + } + }, IGNORED("X") { @Override public CharHandler parseCodes(String[] codeStrings) { return IGNORED_CHAR_HANDLER; @@ -128,7 +134,7 @@ public class GeneralLegacyIndexCodes { */ abstract static class CharHandler { public abstract Type getType(); - public byte[] getInlineBytes() { + public byte[] getInlineBytes(char c) { return null; } public byte[] getExtraBytes() { @@ -159,7 +165,7 @@ public class GeneralLegacyIndexCodes { @Override public Type getType() { return Type.SIMPLE; } - @Override public byte[] getInlineBytes() { + @Override public byte[] getInlineBytes(char c) { return _bytes; } } @@ -177,7 +183,7 @@ public class GeneralLegacyIndexCodes { @Override public Type getType() { return Type.INTERNATIONAL; } - @Override public byte[] getInlineBytes() { + @Override public byte[] getInlineBytes(char c) { return _bytes; } @Override public byte[] getExtraBytes() { @@ -233,7 +239,7 @@ public class GeneralLegacyIndexCodes { @Override public Type getType() { return Type.INTERNATIONAL_EXT; } - @Override public byte[] getInlineBytes() { + @Override public byte[] getInlineBytes(char c) { return _bytes; } @Override public byte[] getExtraBytes() { @@ -255,7 +261,7 @@ public class GeneralLegacyIndexCodes { @Override public Type getType() { return Type.SIGNIFICANT; } - @Override public byte[] getInlineBytes() { + @Override public byte[] getInlineBytes(char c) { return _bytes; } @Override public boolean isSignificantChar() { @@ -270,17 +276,63 @@ public class GeneralLegacyIndexCodes { } }; - /** alternate shared CharHandler instance for "surrogate" chars (which we do - not handle) */ - static final CharHandler SURROGATE_CHAR_HANDLER = new CharHandler() { + /** the surrogate char bufs are computed on the fly. re-use a buffer for + those */ + private static final ThreadLocal SURROGATE_CHAR_BUF = + ThreadLocal.withInitial(() -> new byte[2]); + private static final byte[] SURROGATE_EXTRA_BYTES = {0x3f}; + + private static abstract class SurrogateCharHandler extends CharHandler { @Override public Type getType() { - return Type.IGNORED; + return Type.SURROGATE; } - @Override public byte[] getInlineBytes() { - throw new IllegalStateException( - "Surrogate pair chars are not handled"); + @Override public byte[] getExtraBytes() { + return SURROGATE_EXTRA_BYTES; } - }; + protected static byte[] toInlineBytes(int idxC) { + byte[] bytes = SURROGATE_CHAR_BUF.get(); + bytes[0] = (byte)((idxC >>> 8) & 0xFF); + bytes[1] = (byte)(idxC & 0xFF); + return bytes; + } + } + + /** shared CharHandler instance for "high surrogate" chars (which are + computed) */ + static final CharHandler HIGH_SURROGATE_CHAR_HANDLER = + new SurrogateCharHandler() { + @Override public byte[] getInlineBytes(char c) { + // the high sorrogate bytes seems to be computed from a fixed offset + int idxC = asUnsignedChar(c) - 10238; + return toInlineBytes(idxC); + } + }; + + /** shared CharHandler instance for "low surrogate" chars (which are + computed) */ + static final CharHandler LOW_SURROGATE_CHAR_HANDLER = + new SurrogateCharHandler() { + @Override public byte[] getInlineBytes(char c) { + // the low surrogate bytes are computed with a specific value based in + // its location in a 1024 character block. + int charOffset = (asUnsignedChar(c) - 0xdc00) % 1024; + + int idxOffset = 0; + if(charOffset < 8) { + idxOffset = 9992; + } else if(charOffset < (8 + 254)) { + idxOffset = 9990; + } else if(charOffset < (8 + 254 + 254)) { + idxOffset = 9988; + } else if(charOffset < (8 + 254 + 254 + 254)) { + idxOffset = 9986; + } else { + idxOffset = 9984; + } + int idxC = asUnsignedChar(c) - idxOffset; + return toInlineBytes(idxC); + } + }; static final char FIRST_CHAR = (char)0x0000; static final char LAST_CHAR = (char)0x00FF; @@ -349,9 +401,12 @@ public class GeneralLegacyIndexCodes { for(int i = start; i <= end; ++i) { char c = (char)i; CharHandler ch = null; - if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { + if(Character.isHighSurrogate(c)) { // surrogate chars are not included in the codes files - ch = SURROGATE_CHAR_HANDLER; + ch = HIGH_SURROGATE_CHAR_HANDLER; + } else if(Character.isLowSurrogate(c)) { + // surrogate chars are not included in the codes files + ch = LOW_SURROGATE_CHAR_HANDLER; } else { String codeLine = reader.readLine(); ch = parseCodes(prefixMap, codeLine); @@ -529,7 +584,7 @@ public class GeneralLegacyIndexCodes { CharHandler ch = getCharHandler(c); int curCharOffset = charOffset; - byte[] bytes = ch.getInlineBytes(); + byte[] bytes = ch.getInlineBytes(c); if(bytes != null) { // write the "inline" codes immediately bout.write(bytes); @@ -667,7 +722,6 @@ public class GeneralLegacyIndexCodes { private static void writeExtraCodes( int charOffset, byte[] bytes, byte extraCodeModifier, ExtraCodesStream extraCodes) - throws IOException { // we fill in a placeholder value for any chars w/out extra codes int numChars = extraCodes.getNumChars(); @@ -712,7 +766,6 @@ public class GeneralLegacyIndexCodes { */ private static boolean trimExtraCodes(ByteStream extraCodes, byte minTrimCode, byte maxTrimCode) - throws IOException { if(extraCodes == null) { return false; @@ -730,7 +783,6 @@ public class GeneralLegacyIndexCodes { private static void writeUnprintableCodes( int charOffset, byte[] bytes, ByteStream unprintableCodes, ExtraCodesStream extraCodes) - throws IOException { // the offset seems to be calculated based on the number of bytes in the // "extra codes" part of the entry (even if there are no extra codes bytes @@ -764,7 +816,6 @@ public class GeneralLegacyIndexCodes { * Encode the given crazy code bytes into the given byte stream. */ private static void writeCrazyCodes(ByteStream crazyCodes, ByteStream bout) - throws IOException { // CRAZY_CODE_2 flags at the end are ignored, so ditch them trimExtraCodes(crazyCodes, CRAZY_CODE_2, CRAZY_CODE_2); diff --git a/src/test/data/V2010/testEmoticonsV2010.accdb b/src/test/data/V2010/testEmoticonsV2010.accdb new file mode 100755 index 0000000000000000000000000000000000000000..8b70b95c9500da05c485324962e8440f2bbd62c5 GIT binary patch literal 385024 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 limit) { + break; + } } } diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java index cfcca83..ce4bb52 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java @@ -64,7 +64,17 @@ public class IndexCodesTest extends TestCase { public void testIndexCodes() throws Exception { - for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX_CODES, true)) { + doTestDb(Basename.INDEX_CODES); + } + + public void testEmoticons() throws Exception + { + doTestDb(Basename.EMOTICONS); + } + + private static void doTestDb(Basename dbBaseName) throws Exception + { + for (final TestDB testDB : TestDB.getSupportedForBasename(dbBaseName, true)) { Database db = openMem(testDB); db.setDateTimeType(DateTimeType.DATE); diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java index 0f6c889..2379891 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java @@ -58,7 +58,8 @@ public class JetFormatTest extends TestCase { CALC_FIELD("calcFieldTest"), BINARY_INDEX("binIdxTest"), OLD_DATES("oldDates"), - EXT_DATE("extDateTest"); + EXT_DATE("extDateTest"), + EMOTICONS("testEmoticons"); private final String _basename; -- 2.39.5