/// <summary>Encode the given crazy code bytes into the given byte stream.</summary>
 /// <remarks>Encode the given crazy code bytes into the given byte stream.</remarks>
 /// <exception cref="System.IO.IOException"></exception>
 private static void WriteCrazyCodes(ByteUtil.ByteStream crazyCodes, ByteUtil.ByteStream
                                     bout)
 {
     // CRAZY_CODE_2 flags at the end are ignored, so ditch them
     TrimExtraCodes(crazyCodes, CRAZY_CODE_2, CRAZY_CODE_2);
     if (crazyCodes.GetLength() > 0)
     {
         // the crazy codes get encoded into 6 bit sequences where each code is 2
         // bits (where the first 2 bits in the byte are a common prefix).
         byte curByte = CRAZY_CODE_START;
         int  idx     = 0;
         for (int i = 0; i < crazyCodes.GetLength(); ++i)
         {
             byte nextByte = crazyCodes.Get(i);
             nextByte <<= ((2 - idx) * 2);
             curByte   |= nextByte;
             ++idx;
             if (idx == 3)
             {
                 // write current byte and reset
                 bout.Write(curByte);
                 curByte = CRAZY_CODE_START;
                 idx     = 0;
             }
         }
         // write last byte
         if (idx > 0)
         {
             bout.Write(curByte);
         }
     }
     // write crazy code suffix (note, we write this even if all the codes are
     // trimmed
     bout.Write(CRAZY_CODES_SUFFIX);
 }
        /// <summary>Encodes the given unprintable char codes in the given stream.</summary>
        /// <remarks>Encodes the given unprintable char codes in the given stream.</remarks>
        /// <exception cref="System.IO.IOException"></exception>
        private static void WriteUnprintableCodes(int charOffset, byte[] bytes, ByteUtil.ByteStream
                                                  unprintableCodes, GeneralLegacyIndexCodes.ExtraCodesStream extraCodes)
        {
            // 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
            // actually written in the final entry).
            int unprintCharOffset = charOffset;

            if (extraCodes != null)
            {
                // we need to account for some extra codes which have not been written
                // yet.  additionally, any unprintable bytes added to the beginning of
                // the extra codes are ignored.
                unprintCharOffset = extraCodes.GetLength() + (charOffset - extraCodes.GetNumChars
                                                                  ()) - extraCodes.GetUnprintablePrefixLen();
            }
            // we write a whacky combo of bytes for each unprintable char which
            // includes a funky offset and extra char itself
            int offset = (UNPRINTABLE_COUNT_START + (UNPRINTABLE_COUNT_MULTIPLIER * unprintCharOffset
                                                     )) | UNPRINTABLE_OFFSET_FLAGS;

            // write offset as big-endian short
            unprintableCodes.Write((offset >> 8) & unchecked ((int)(0xFF)));
            unprintableCodes.Write(offset & unchecked ((int)(0xFF)));
            unprintableCodes.Write(UNPRINTABLE_MIDFIX);
            unprintableCodes.Write(bytes);
        }
 /// <summary>
 /// 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.
 /// </summary>
 /// <remarks>
 /// 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.
 /// </remarks>
 /// <exception cref="System.IO.IOException"></exception>
 private static bool TrimExtraCodes(ByteUtil.ByteStream extraCodes, byte minTrimCode
                                    , byte maxTrimCode)
 {
     if (extraCodes == null)
     {
         return(false);
     }
     extraCodes.TrimTrailing(minTrimCode, maxTrimCode);
     // anything left?
     return(extraCodes.GetLength() > 0);
 }
        /// <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);
        }
Пример #5
0
 public virtual void WriteTo(ByteUtil.ByteStream @out)
 {
     @out.Write(_bytes, 0, _length);
 }