/// <summary> /// Converts an index value for a text column into the entry value (which /// is based on a variety of nifty codes). /// </summary> /// <remarks> /// Converts an index value for a text column into the entry value (which /// is based on a variety of nifty codes). /// </remarks> /// <exception cref="System.IO.IOException"></exception> internal virtual void WriteNonNullIndexTextValue(object value, ByteUtil.ByteStream bout, bool isAscending) { // first, convert to string string str = Column.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 = Sharpen.Runtime.Substring(str, 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 GeneralLegacyIndexCodes.ExtraCodesStream extraCodes = null; ByteUtil.ByteStream unprintableCodes = null; ByteUtil.ByteStream crazyCodes = null; int charOffset = 0; for (int i = 0; i < str.Length; ++i) { char c = str[i]; GeneralLegacyIndexCodes.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.GetEncodingType() == GeneralLegacyIndexCodes.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 GeneralLegacyIndexCodes.ExtraCodesStream(str.Length); } // keep track of the extra codes for later WriteExtraCodes(curCharOffset, bytes, extraCodeModifier, extraCodes); } bytes = ch.GetUnprintableBytes(); if (bytes != null) { if (unprintableCodes == null) { unprintableCodes = new ByteUtil.ByteStream(); } // keep track of the unprintable codes for later WriteUnprintableCodes(curCharOffset, bytes, unprintableCodes, extraCodes); } byte crazyFlag = ch.GetCrazyFlag(); if (crazyFlag != 0) { if (crazyCodes == null) { crazyCodes = new ByteUtil.ByteStream(); } // keep track of the crazy flags for later crazyCodes.Write(crazyFlag); } } // write end text flag bout.Write(END_TEXT); bool hasExtraCodes = TrimExtraCodes(extraCodes, unchecked ((byte)0), INTERNATIONAL_EXTRA_PLACEHOLDER ); bool hasUnprintableCodes = (unprintableCodes != null); bool hasCrazyCodes = (crazyCodes != null); if (hasExtraCodes || hasUnprintableCodes || hasCrazyCodes) { // we write all the international extra bytes first if (hasExtraCodes) { extraCodes.WriteTo(bout); } if (hasCrazyCodes || hasUnprintableCodes) { // write 2 more end flags bout.Write(END_TEXT); bout.Write(END_TEXT); // next come the crazy flags if (hasCrazyCodes) { WriteCrazyCodes(crazyCodes, bout); // if we are writing unprintable codes after this, tack on another // code if (hasUnprintableCodes) { bout.Write(CRAZY_CODES_UNPRINT_SUFFIX); } } // then we write all the unprintable extra bytes if (hasUnprintableCodes) { // write another end flag bout.Write(END_TEXT); unprintableCodes.WriteTo(bout); } } } // 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); }