/// <summary>
        /// Perform the steps necessary to deserialize a string.
        /// </summary>
        /// <param name="source">The reader providing the input data.</param>
        /// <returns>A string value from the reader.</returns>
        public override string Read(IWireStreamReaderStrategy source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            //Review the source for Trinitycore's string reading for their ByteBuffer (payload/packet) Type.
            //(ctr+f >> for std::string): http://www.trinitycore.net/d1/d17/ByteBuffer_8h_source.html
            //They use 0 byte to terminate the string in the stream

            //TODO: We can likely do some fancy pointer stuff to make this much cheaper.
            //Read a byte from the stream; Stop when we find a 0
            List <byte> stringBytes = new List <byte>();

            //This is used to track larger than 1 char null terminators
            int zeroByteCountFound = 0;

            //How many characters have been counted
            int currentCharCount = 0;

            do
            {
                byte currentByte = source.ReadByte();
                currentCharCount++;

                stringBytes.Add(currentByte);

                //If we find a 0 byte we need to track it
                //char could be 1 byte or even 4 so we need to reset
                //if we encounter an actual character before we find all
                //null terminator bytes
                if (currentByte == 0)
                {
                    zeroByteCountFound++;
                }
                else
                {
                    zeroByteCountFound = 0;
                }

                //if we found 4 0 bytes in arow but we didn't find a full char set of CharacterSize
                //then we should reset. This can happen if you have {5 0 0 0} {0 0 0 0} it will stop after the first 4
                //But with this is will read the whole {0 0 0 0}.
                if (currentCharCount % CharacterSize == 0 && zeroByteCountFound < CharacterSize)
                {
                    zeroByteCountFound = 0;
                }
            } while(zeroByteCountFound < CharacterSize);

            //TODO: Invesitgate expected WoW/TC behavior for strings of length 0. Currently violates contract for return type.
            //I have decided to support empty strings instead of null
            return(stringBytes.Count - CharacterSize <= 0 ? "" : EncodingStrategy.GetString(stringBytes.ToArray(), 0, Math.Max(0, stringBytes.Count - CharacterSize)));
        }
        /// <inheritdoc />
        public override async Task <string> ReadAsync(IWireStreamReaderStrategyAsync source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            //See sync method for doc

            //TODO: Find an average size for WoW strings
            List <byte> stringBytes = new List <byte>();

            //This is used to track larger than 1 char null terminators
            int zeroByteCountFound = 0;

            //How many characters have been counted
            int currentCharCount = 0;

            do
            {
                byte currentByte = await source.ReadByteAsync()
                                   .ConfigureAwait(false);

                currentCharCount++;

                stringBytes.Add(currentByte);

                //If we find a 0 byte we need to track it
                //char could be 1 byte or even 4 so we need to reset
                //if we encounter an actual character before we find all
                //null terminator bytes
                if (currentByte == 0)
                {
                    zeroByteCountFound++;
                }
                else
                {
                    zeroByteCountFound = 0;
                }

                //if we found 4 0 bytes in arow but we didn't find a full char set of CharacterSize
                //then we should reset. This can happen if you have {5 0 0 0} {0 0 0 0} it will stop after the first 4
                //But with this is will read the whole {0 0 0 0}.
                if (currentCharCount % CharacterSize == 0 && zeroByteCountFound < CharacterSize)
                {
                    zeroByteCountFound = 0;
                }
            } while(zeroByteCountFound < CharacterSize);

            //TODO: Invesitgate expected WoW/TC behavior for strings of length 0. Currently violates contract for return type.
            //I have decided to support empty strings instead of null
            return(stringBytes.Count - CharacterSize <= 0 ? "" : EncodingStrategy.GetString(stringBytes.ToArray(), 0, Math.Max(0, stringBytes.Count - CharacterSize)));
        }
        /// <inheritdoc />
        public override async Task <string> ReadAsync(IWireStreamReaderStrategyAsync source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            //The size must come from the strategy provided
            int size = CharacterSize * await sizeProvider.SizeAsync(source)
                       .ConfigureAwait(false);

            byte[] bytes = await source.ReadBytesAsync(size)
                           .ConfigureAwait(false);

            return(EncodingStrategy.GetString(bytes).TrimEnd(NullTermincatorCharacterArray));
        }
        /// <inheritdoc />
        public override string Read(IWireStreamReaderStrategy source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            //The size must come from the strategy provided
            //TODO: Should we expect char size or byte size?
            int size = CharacterSize * sizeProvider.Size(source);

            byte[] bytes = source.ReadBytes(size);

            //TODO: Pointer hack for preformance
            //This is the only way to remove padding that I know of
            //There may be a more efficient way of removing the padding
            //There is actually an unsafe pointer hack to improve preformance here too.
            //profile and add later.
            return(EncodingStrategy.GetString(bytes).TrimEnd(NullTermincatorCharacterArray));
        }
Пример #5
0
 protected virtual unsafe string ReadEncodedString(byte *bytes, int trueStringSize)
 {
     return(EncodingStrategy.GetString(bytes, trueStringSize));
 }