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); }
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; }