public void WriteString(string name, char[] value, int length, int maxLength, OverrunBehaviour overrunBehaviour)
    {
        ValidateOrGenerateSchema(name, NetworkSchema.FieldType.String, 0, false, 0, maxLength);

        GameDebug.Assert(maxLength <= s_ByteBuffer.Length, "NetworkWriter: Max length has to be less than {0}", s_ByteBuffer.Length);
        GameDebug.Assert((maxLength & 0x3) == 0, "MaxLength has to be 32bit aligned");

        var byteCount = 0;

        if (length > 0)
        {
            // Ensure the (utf-8) *encoded* string is not too big. If it is, cut it off,
            // convert back to unicode and then back again to utf-8. This little dance gives
            // a valid utf-8 string within the buffer size.
            byteCount = NetworkConfig.encoding.GetBytes(value, 0, length, s_ByteBuffer, 0);
            if (byteCount > maxLength)
            {
                if (overrunBehaviour == OverrunBehaviour.AssertMaxLength)
                {
                    GameDebug.Assert(false, "NetworkWriter : string {0} too long. (Using {1}/{2} allowed encoded bytes): ", value, byteCount, maxLength);
                }
                // truncate
                var truncWithBadEnd = NetworkConfig.encoding.GetString(s_ByteBuffer, 0, maxLength);
                var truncOk         = truncWithBadEnd.Substring(0, truncWithBadEnd.Length - 1);
                var newbyteCount    = NetworkConfig.encoding.GetBytes(truncOk, 0, truncOk.Length, s_ByteBuffer, 0);

                if (overrunBehaviour == OverrunBehaviour.WarnAndTrunc)
                {
                    GameDebug.LogWarning(string.Format("NetworkWriter : truncated string with {0} bytes. (result: {1})", byteCount - newbyteCount, truncOk));
                }
                byteCount = newbyteCount;
                GameDebug.Assert(byteCount <= maxLength, "String encoding failed");
            }
        }

        m_Output[m_Position++] = (uint)byteCount;
        byte *dst = (byte *)(m_Output + m_Position);
        int   i   = 0;

        for (; i < byteCount; ++i)
        {
            *dst++ = s_ByteBuffer[i];
        }
        for (; i < maxLength; ++i)
        {
            *dst++ = 0;
        }

        GameDebug.Assert(((uint)dst & 0x3) == 0, "Expected to stay aligned!");
        m_Position += maxLength / 4;
    }
    public void WriteString(string name, string value, int maxLength = 64, OverrunBehaviour overrunBehaviour = OverrunBehaviour.WarnAndTrunc)
    {
        if (value == null)
        {
            value = "";
        }

        if (value.Length > _writeStringBuf.Length)
        {
            _writeStringBuf = new char[_writeStringBuf.Length * 2];
        }

        value.CopyTo(0, _writeStringBuf, 0, value.Length);
        WriteString(name, _writeStringBuf, value.Length, maxLength, overrunBehaviour);
    }
Exemple #3
0
    public void WriteString(string name, char[] value, int length, int maxLength, OverrunBehaviour overrunBehaviour)
    {
        ValidateOrGenerateSchema(name, NetworkSchema.FieldType.String, 0, false, 0, maxLength);
        if (length == 0)
        {
            m_Output.WriteByteArray(null, 0, 0, maxLength);
            return;
        }

        GameDebug.Assert(maxLength <= s_ByteBuffer.Length, "NetworkWriter: Max length has to be less than {0}", s_ByteBuffer.Length);

        // Ensure the (utf-8) *encoded* string is not too big. If it is, cut it off,
        // convert back to unicode and then back again to utf-8. This little dance gives
        // a valid utf-8 string within the buffer size.
        var byteCount = NetworkConfig.encoding.GetBytes(value, 0, length, s_ByteBuffer, 0);

        if (byteCount > maxLength)
        {
            if (overrunBehaviour == OverrunBehaviour.AssertMaxLength)
            {
                GameDebug.Assert(false, "NetworkWriter : string {0} too long. (Using {1}/{2} allowed encoded bytes): ", value, byteCount, maxLength);
            }
            // truncate
            var truncWithBadEnd = NetworkConfig.encoding.GetString(s_ByteBuffer, 0, maxLength);
            var truncOk         = truncWithBadEnd.Substring(0, truncWithBadEnd.Length - 1);
            var newbyteCount    = NetworkConfig.encoding.GetBytes(truncOk, 0, truncOk.Length, s_ByteBuffer, 0);

            if (overrunBehaviour == OverrunBehaviour.WarnAndTrunc)
            {
                GameDebug.LogWarning(string.Format("NetworkWriter : truncated string with {0} bytes. (result: {1})", byteCount - newbyteCount, truncOk));
            }
            byteCount = newbyteCount;
            GameDebug.Assert(byteCount <= maxLength);
        }

        m_Output.WriteByteArray(s_ByteBuffer, 0, byteCount, maxLength);
    }
    public void WriteNativeString(string name, NativeString64 value, int maxLength = 64, OverrunBehaviour overrunBehaviour = OverrunBehaviour.WarnAndTrunc)
    {
        ValidateOrGenerateSchema(name, NetworkSchema.FieldType.String, 0, false, 0, maxLength);

        GameDebug.Assert((maxLength & 0x3) == 0, "MaxLength has to be 32bit aligned");

        var bytes     = &value.buffer.byte0000;
        var byteCount = maxLength;

        if (value.LengthInBytes > maxLength)
        {
            if (overrunBehaviour == OverrunBehaviour.AssertMaxLength)
            {
                GameDebug.Assert(false, "NetworkWriter : string {0} too long. (Using {1}/{2} allowed encoded bytes): ", value, byteCount, maxLength);
            }

            // truncate
            byteCount = maxLength;

            // Find the last non-trailer code unit and attempt to get its code point
            // If that fails truncate right before this non-trailer code unit
            // TODO: NativeString will get API for truncating, replace with that when it's ready
            var lastNonTrailerIndex = byteCount - 1;
            while (Unicode.NotTrailer(bytes[lastNonTrailerIndex]))
            {
                lastNonTrailerIndex--;
            }
            var offset          = lastNonTrailerIndex;
            var conversionError = Unicode.Utf8ToUcs(out var rune, bytes, ref offset, maxLength);
            if (conversionError != ConversionError.None)
            {
                byteCount = lastNonTrailerIndex;
            }
        }

        m_Output[m_Position++] = (uint)byteCount;
        byte *dst = (byte *)(m_Output + m_Position);
        int   i   = 0;

        for (; i < byteCount; ++i)
        {
            *dst++ = bytes[i];
        }
        for (; i < maxLength; ++i)
        {
            *dst++ = 0;
        }

        GameDebug.Assert(((uint)dst & 0x3) == 0, "Expected to stay aligned!");
        m_Position += maxLength / 4;
    }