Browse Source

initial support for writing access 97 indexes

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/a97_indexes@1309 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-3.5.0
James Ahlborn 4 years ago
parent
commit
e47aa25994

+ 107
- 22
src/main/java/com/healthmarketscience/jackcess/impl/GeneralLegacyIndexCodes.java View File

@@ -52,20 +52,20 @@ public class GeneralLegacyIndexCodes {
// international char is replaced with ascii char.
// pattern for international chars in the extra bytes:
// [ 02 (for each normal char) ] [ <symbol_code> (for each inat char) ]
static final byte INTERNATIONAL_EXTRA_PLACEHOLDER = (byte)0x02;
static final byte INTERNATIONAL_EXTRA_PLACEHOLDER = (byte)0x02;

// see Index.writeCrazyCodes for details on writing crazy codes
static final byte CRAZY_CODE_START = (byte)0x80;
static final byte CRAZY_CODE_1 = (byte)0x02;
static final byte CRAZY_CODE_2 = (byte)0x03;
static final byte[] CRAZY_CODES_SUFFIX =
static final byte[] CRAZY_CODES_SUFFIX =
new byte[]{(byte)0xFF, (byte)0x02, (byte)0x80, (byte)0xFF, (byte)0x80};
static final byte CRAZY_CODES_UNPRINT_SUFFIX = (byte)0xFF;

// stash the codes in some resource files
private static final String CODES_FILE =
private static final String CODES_FILE =
DatabaseImpl.RESOURCE_PATH + "index_codes_genleg.txt";
private static final String EXT_CODES_FILE =
private static final String EXT_CODES_FILE =
DatabaseImpl.RESOURCE_PATH + "index_codes_ext_genleg.txt";

/**
@@ -267,7 +267,7 @@ public class GeneralLegacyIndexCodes {
private static final CharHandler[] _values = loadCodes(
CODES_FILE, FIRST_CHAR, LAST_CHAR);
}
private static final class ExtCodes
{
/** handlers for the rest of the chars in BMP 0. use nested class to
@@ -276,9 +276,9 @@ public class GeneralLegacyIndexCodes {
EXT_CODES_FILE, FIRST_EXT_CHAR, LAST_EXT_CHAR);
}

static final GeneralLegacyIndexCodes GEN_LEG_INSTANCE =
static final GeneralLegacyIndexCodes GEN_LEG_INSTANCE =
new GeneralLegacyIndexCodes();
GeneralLegacyIndexCodes() {
}

@@ -316,7 +316,7 @@ public class GeneralLegacyIndexCodes {
reader = new BufferedReader(
new InputStreamReader(
DatabaseImpl.getResourceAsStream(codesFilePath), "US-ASCII"));
int start = asUnsignedChar(firstChar);
int end = asUnsignedChar(lastChar);
for(int i = start; i <= end; ++i) {
@@ -357,7 +357,7 @@ public class GeneralLegacyIndexCodes {
/**
* Returns a SimpleCharHandler parsed from the given index code strings.
*/
private static CharHandler parseSimpleCodes(String[] codeStrings)
private static CharHandler parseSimpleCodes(String[] codeStrings)
{
if(codeStrings.length != 1) {
throw new IllegalStateException("Unexpected code strings " +
@@ -397,7 +397,7 @@ public class GeneralLegacyIndexCodes {
* Returns a UnprintableExtCharHandler parsed from the given index code
* strings.
*/
private static CharHandler parseUnprintableExtCodes(String[] codeStrings)
private static CharHandler parseUnprintableExtCodes(String[] codeStrings)
{
if(codeStrings.length != 1) {
throw new IllegalStateException("Unexpected code strings " +
@@ -415,7 +415,7 @@ public class GeneralLegacyIndexCodes {
* Returns a InternationalExtCharHandler parsed from the given index code
* strings.
*/
private static CharHandler parseInternationalExtCodes(String[] codeStrings)
private static CharHandler parseInternationalExtCodes(String[] codeStrings)
{
if(codeStrings.length != 3) {
throw new IllegalStateException("Unexpected code strings " +
@@ -484,7 +484,7 @@ public class GeneralLegacyIndexCodes {
// record pprevious entry length so we can do any post-processing
// necessary for this entry (handling descending)
int prevLength = bout.getLength();
// now, convert each character to a "code" of one or more bytes
ExtraCodesStream extraCodes = null;
ByteStream unprintableCodes = null;
@@ -526,12 +526,12 @@ public class GeneralLegacyIndexCodes {
if(unprintableCodes == null) {
unprintableCodes = new ByteStream();
}
// keep track of the unprintable codes for later
writeUnprintableCodes(curCharOffset, bytes, unprintableCodes,
extraCodes);
}
byte crazyFlag = ch.getCrazyFlag();
if(crazyFlag != 0) {
if(crazyCodes == null) {
@@ -580,7 +580,7 @@ public class GeneralLegacyIndexCodes {

// write another end flag
bout.write(END_TEXT);
unprintableCodes.writeTo(bout);
}
}
@@ -592,14 +592,99 @@ public class GeneralLegacyIndexCodes {
// we actually write the end byte before flipping the bytes, and write
// another one after flipping
bout.write(END_EXTRA_TEXT);
// flip the bytes that we have written thus far for this text value
IndexData.flipBytes(bout.getBytes(), prevLength,
IndexData.flipBytes(bout.getBytes(), prevLength,
(bout.getLength() - prevLength));
}

// write end extra text
bout.write(END_EXTRA_TEXT);
bout.write(END_EXTRA_TEXT);
}

/**
* Converts a 97 index value for a text column into the entry value (which
* is based on a variety of nifty codes).
*/
void writeNonNull97IndexTextValue(
Object value, ByteStream bout, boolean isAscending)
throws IOException
{
// NOTE, this should probably be in Gen97TextColumnDescriptor but it was
// easier to add here than make everything private non-private.

// first, convert to string
String str = ColumnImpl.toCharSequence(value).toString();

// all text columns (including memos) are only indexed up to the max
// number of chars in a VARCHAR column
if(str.length() > MAX_TEXT_INDEX_CHAR_LENGTH) {
str = str.substring(0, MAX_TEXT_INDEX_CHAR_LENGTH);
}

// record pprevious entry length so we can do any post-processing
// necessary for this entry (handling descending)
int prevLength = bout.getLength();

// now, convert each character to a "code" of one or more bytes
ExtraCodesStream extraCodes = null;
int charOffset = 0;
for(int i = 0; i < str.length(); ++i) {

char c = str.charAt(i);
CharHandler ch = getCharHandler(c);

int curCharOffset = charOffset;
byte[] bytes = ch.getInlineBytes();
if(bytes != null) {
// write the "inline" codes immediately
bout.write(bytes);

// only increment the charOffset for chars with inline codes
++charOffset;
}

if(ch.getType() == Type.SIMPLE) {
// common case, skip further code handling
continue;
}

bytes = ch.getExtraBytes();
byte extraCodeModifier = ch.getExtraByteModifier();
if((bytes != null) || (extraCodeModifier != 0)) {
if(extraCodes == null) {
extraCodes = new ExtraCodesStream(str.length());
}

// keep track of the extra codes for later
writeExtraCodes(curCharOffset, bytes, extraCodeModifier, extraCodes);
}
}

// FIXME, how to handle extra codes for non ascending?
boolean hasExtraCodes = trimExtraCodes(
extraCodes, (byte)0, INTERNATIONAL_EXTRA_PLACEHOLDER);
if(hasExtraCodes) {

extraCodes.writeTo(bout);

} else {

// handle descending order by inverting the bytes
if(!isAscending) {

// we actually write the end byte before flipping the bytes, and write
// another one after flipping
bout.write(END_EXTRA_TEXT);

// flip the bytes that we have written thus far for this text value
IndexData.flipBytes(bout.getBytes(), prevLength,
(bout.getLength() - prevLength));
}

// write end extra text
bout.write(END_EXTRA_TEXT);
}
}

/**
@@ -619,7 +704,7 @@ public class GeneralLegacyIndexCodes {
}

if(bytes != null) {
// write the actual extra codes and update the number of chars
extraCodes.write(bytes);
extraCodes.incrementNumChars(1);
@@ -696,7 +781,7 @@ public class GeneralLegacyIndexCodes {
// write offset as big-endian short
unprintableCodes.write((offset >> 8) & 0xFF);
unprintableCodes.write(offset & 0xFF);
unprintableCodes.write(UNPRINTABLE_MIDFIX);
unprintableCodes.write(bytes);
}
@@ -748,7 +833,7 @@ public class GeneralLegacyIndexCodes {
private static final class ExtraCodesStream extends ByteStream
{
private int _numChars;
private int _unprintablePrefixLen;
private int _unprintablePrefixLen;

private ExtraCodesStream(int length) {
super(length);
@@ -757,7 +842,7 @@ public class GeneralLegacyIndexCodes {
public int getNumChars() {
return _numChars;
}
public void incrementNumChars(int inc) {
_numChars += inc;
}

Loading…
Cancel
Save