APIdia Launch Partner
Top Description Inners Fields Constructors Methods
io.github.spannm.jackcess.impl

public Class GeneralLegacyIndexCodes

extends Object
Class Inheritance
Known Direct Subclasses
io.github.spannm.jackcess.impl.General97IndexCodes, io.github.spannm.jackcess.impl.GeneralIndexCodes
Annotations
@SuppressWarnings:PMD.FieldDeclarationsShouldBeAtStartOfClass
Imports
io.github.spannm.jackcess.impl.ByteUtil.ByteStream, java.io.BufferedReader, .IOException, .InputStreamReader, .UncheckedIOException, java.nio.charset.StandardCharsets, java.util.Arrays, .HashMap, .Map

Encoding logic for MS Access "General Legacy" (Access 2000–2007) text index entries.

MS Access stores text index values in a proprietary, order-preserving byte format rather than using standard Unicode sort keys. This class implements that format for the "General Legacy" sort order (LCID 1033, version 0). GeneralIndexCodes (Access 2010+) and General97IndexCodes (Access 97) extend or mirror this class for their respective format variants.

Byte-format overview

Each character in the input string contributes zero or more bytes to up to four output sections, which are written sequentially:
  1. Inline bytes – the primary sort key bytes for the character. Written immediately into the main output stream. Most printable ASCII characters contribute exactly one byte here.
  2. 1 (0x01) – a terminator byte written after all inline bytes.
  3. Extra / international bytes (optional) – diacritic / accent weights for characters that have a base character plus a modifier. Each normal char contributes a placeholder byte (INTERNATIONAL_EXTRA_PLACEHOLDER = 0x02); each accented char contributes its accent code. Written after the terminator if any accented characters were present.
  4. Unprintable bytes (optional) – position-encoded bytes for control characters and other non-printable code points. Written after extra bytes if present.
  5. Crazy codes (optional) – additional flags for a small set of special characters that affect sort order in complex ways. Written last.

Character handlers (CharHandler)

Each of the 65 536 BMP characters is mapped to a CharHandler instance that supplies the byte values for each of the four sections above. Handlers for code points U+0000–U+00FF are loaded from index_codes_genleg.txt; handlers for U+0100–U+FFFF from index_codes_ext_genleg.txt. Both files live in the Jackcess classpath resources under DatabaseImpl#RESOURCE_PATH.

Relevance for non-General sort orders

Any sort order other than the three General variants (LCID 1033) currently lacks a corresponding implementation in Jackcess. Attempting to write an index on a text column with, for example, Turkish sort order (LCID 1055) will cause IndexData#setUnsupportedReason to be called and the index to become read-only. Adding support for a new locale requires reverse-engineering the MS Access byte tables for that locale and providing a new *IndexCodes class plus a corresponding IndexData.ColumnDescriptor subclass — not using java.text.Collator#getCollationKey, whose byte format is JVM-internal and incompatible with the MS Access format.
See Also
GeneralIndexCodes, General97IndexCodes, IndexData#newColumnDescriptor

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv abstract static class
GeneralLegacyIndexCodes.CharHandler

Holds the MS Access index byte-encoding information for a single Unicode character.

private static class
private static class
private static class
GeneralLegacyIndexCodes.ExtraCodesStream

Extension of ByteStream which keeps track of an additional char count and the length of any "unprintable" code prefix.

private static class
GeneralLegacyIndexCodes.InternationalCharHandler

CharHandler for Type.INTERNATIONAL

private static class
GeneralLegacyIndexCodes.InternationalExtCharHandler

CharHandler for Type.INTERNATIONAL_EXT

private static class
GeneralLegacyIndexCodes.SignificantCharHandler

CharHandler for Type.SIGNIFICANT

private static class
GeneralLegacyIndexCodes.SimpleCharHandler

CharHandler for Type.SIMPLE

pack-priv abstract static class
GeneralLegacyIndexCodes.SurrogateCharHandler

Base for the handlers of the surrogate chars, which are computed rather than read from the codes files.

pack-priv static interface
GeneralLegacyIndexCodes.SurrogateCharHandlers

Supplies the handler for a surrogate char.

pack-priv static enum
GeneralLegacyIndexCodes.Type

Enum which classifies the types of char encoding strategies used when creating text index entries.

private static class
GeneralLegacyIndexCodes.UnprintableCharHandler

CharHandler for Type.UNPRINTABLE

private static class
GeneralLegacyIndexCodes.UnprintableExtCharHandler

CharHandler for Type.UNPRINTABLE_EXT

Field Summary

Modifier and TypeField and Description
private static final String
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
pack-priv static final int
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
pack-priv static final byte
private static final String
pack-priv static final char
pack-priv static final char
pack-priv static final GeneralLegacyIndexCodes
pack-priv static final GeneralLegacyIndexCodes.CharHandler
IGNORED_CHAR_HANDLER

shared CharHandler instance for Type.IGNORED

pack-priv static final GeneralLegacyIndexCodes.SurrogateCharHandlers
IGNORED_SURROGATES

the general legacy collation gives a surrogate no weight at all, so both halves of a pair are ignored

pack-priv static final byte
pack-priv static final char
pack-priv static final char
pack-priv static final int
private static final ThreadLocal<byte[]>
SURROGATE_CHAR_BUF

the surrogate char buffers are computed on the fly.

pack-priv static final int
pack-priv static final int
pack-priv static final byte
pack-priv static final int

Constructor Summary

AccessConstructor and Description
pack-priv

Method Summary

Modifier and TypeMethod and Description
pack-priv static int
asUnsignedChar(char c)

Returns an the char value converted to an unsigned char value.

private static byte[]
codesToBytes(String codes, boolean required)

Converts a string of hex encoded bytes to a byte[], optionally throwing an exception if no codes are given.

pack-priv GeneralLegacyIndexCodes.CharHandler
getCharHandler(char c)

Returns the CharHandler for the given character.

pack-priv static GeneralLegacyIndexCodes.CharHandler[]
loadCodes(String codesFilePath, char firstChar, char lastChar)

Loads the CharHandlers for the given range of characters from the resource file with the given name.

pack-priv static GeneralLegacyIndexCodes.CharHandler[]

Returns:

the handlers for the range
loadCodes
(String
resource path of the codes file
codesFilePath
,
char
first char of the range
firstChar
,
char
last char of the range
lastChar
,
GeneralLegacyIndexCodes.SurrogateCharHandlers
source of the handlers for the surrogate chars
surrogates
)

Loads the CharHandlers for the given range of characters from the resource file with the given name, taking the handlers for the surrogate chars from the given source.

private static GeneralLegacyIndexCodes.CharHandler
parseCodes(Map<String, GeneralLegacyIndexCodes.Type> prefixMap, String codeLine)

Returns a CharHandler parsed from the given line from an index codes file.

protected static String
private static boolean
trimExtraCodes(ByteUtil.ByteStream extraCodes, byte minTrimCode, byte maxTrimCode)

Trims any bytes in the given range off of the end of the given stream, returning whether or not there are any bytes left in the given stream after trimming.

private static void
writeCrazyCodes(ByteUtil.ByteStream crazyCodes, ByteUtil.ByteStream bout)

Encode the given crazy code bytes into the given byte stream.

private static void
writeCrazyCodesSuffix(int numCrazyChars, ByteUtil.ByteStream bout)

Encode the suffix which follows the crazy codes into the given byte stream.

private static void
private static void
writeExtraCodes(int charOffset, byte[] bytes, byte extraCodeModifier, GeneralLegacyIndexCodes.ExtraCodesStream extraCodes)

Encodes the given extra code info in the given stream.

pack-priv void
writeNonNullIndexTextValue(Object value, ByteUtil.ByteStream bout, boolean isAscending)

Converts an index value for a text column into the entry value (which is based on a variety of nifty codes).

private static void
writeUnprintableCodes(int charOffset, byte[] bytes, ByteUtil.ByteStream unprintableCodes, GeneralLegacyIndexCodes.ExtraCodesStream extraCodes)

Encodes the given unprintable char codes in the given stream.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait