public static void SendString(DataOutputStream stream, string message) { Task.Run(() => { stream.WriteChars(message); stream.WriteChar(END); }); }
/// <summary> /// Writes an ICU data header. /// Does not write a copyright string. /// </summary> /// <param name="dataFormat"></param> /// <param name="formatVersion"></param> /// <param name="dataVersion"></param> /// <param name="dos"></param> /// <returns>The length of the header (number of bytes written).</returns> /// <exception cref="IOException">From the <see cref="DataOutputStream"/>.</exception> public static int WriteHeader(int dataFormat, int formatVersion, int dataVersion, DataOutputStream dos) { // ucmndata.h MappedData dos.WriteChar(32); // headerSize dos.WriteByte(MAGIC1); dos.WriteByte(MAGIC2); // unicode/udata.h UDataInfo dos.WriteChar(20); // sizeof(UDataInfo) dos.WriteChar(0); // reservedWord dos.WriteByte(1); // isBigEndian dos.WriteByte(CHAR_SET_); // charsetFamily dos.WriteByte(CHAR_SIZE_); // sizeofUChar dos.WriteByte(0); // reservedByte dos.WriteInt32(dataFormat); dos.WriteInt32(formatVersion); dos.WriteInt32(dataVersion); // 8 bytes padding for 32 bytes headerSize (multiple of 16). dos.WriteInt64(0); Debug.Assert(dos.Length == 32); return(32); }
/// <summary> /// Serialize a <see cref="Trie2_16"/> onto an <see cref="Stream"/>. /// </summary> /// <remarks> /// A <see cref="Trie2"/> can be serialized multiple times. /// The serialized data is compatible with ICU4C UTrie2 serialization. /// <see cref="Trie2"/> serialization is unrelated to .NET object serialization. /// </remarks> /// <param name="os">The stream to which the serialized Trie2 data will be written.</param> /// <returns>The number of bytes written.</returns> /// <exception cref="IOException">On an error writing to the <see cref="Stream"/>.</exception> public int Serialize(Stream os) { DataOutputStream dos = new DataOutputStream(os); int bytesWritten = 0; bytesWritten += SerializeHeader(dos); for (int i = 0; i < dataLength; i++) { dos.WriteChar(index[data16 + i]); } bytesWritten += dataLength * 2; return(bytesWritten); }
/// <summary> /// Serializes the build table to an output stream. /// <para/> /// Compacts the build-time trie after all values are set, and then /// writes the serialized form onto an output stream. /// <para/> /// After this, this build-time Trie can only be serialized again and/or closed; /// no further values can be added. /// <para/> /// This function is the rough equivalent of utrie_seriaize() in ICU4C. /// </summary> /// <param name="os">The output stream to which the seriaized trie will be written. /// If nul, the function still returns the size of the serialized Trie.</param> /// <param name="reduceTo16Bits">If true, reduce the data size to 16 bits. The resulting /// serialized form can then be used to create a <see cref="CharTrie"/>.</param> /// <param name="datamanipulate">Builder raw fold method implementation.</param> /// <returns>The number of bytes written to the output stream.</returns> public virtual int Serialize(Stream os, bool reduceTo16Bits, ITrieBuilderDataManipulate datamanipulate) { if (datamanipulate == null) { throw new ArgumentException("Parameters can not be null"); } // fold and compact if necessary, also checks that indexLength is // within limits if (!m_isCompacted_) { // compact once without overlap to improve folding Compact(false); // fold the supplementary part of the index array Fold(datamanipulate); // compact again with overlap for minimum data array length Compact(true); m_isCompacted_ = true; } // is dataLength within limits? int length; if (reduceTo16Bits) { length = m_dataLength_ + m_indexLength_; } else { length = m_dataLength_; } if (length >= MaxDataLength) { throw new IndexOutOfRangeException("Data length too small"); } // struct UTrieHeader { // int32_t signature; // int32_t options (a bit field) // int32_t indexLength // int32_t dataLength length = Trie.HeaderLength + 2 * m_indexLength_; if (reduceTo16Bits) { length += 2 * m_dataLength_; } else { length += 4 * m_dataLength_; } if (os == null) { // No output stream. Just return the length of the serialized Trie, in bytes. return(length); } DataOutputStream dos = new DataOutputStream(os); dos.WriteInt32(Trie.HeaderSignature); int options = Trie.IndexStage1Shift | (Trie.IndexStage2Shift << Trie.HeaderOptionsIndexShift); if (!reduceTo16Bits) { options |= Trie.HeaderOptionsDataIs32Bit; } if (m_isLatin1Linear_) { options |= Trie.HeaderOptionsLatin1IsLinearMask; } dos.WriteInt32(options); dos.WriteInt32(m_indexLength_); dos.WriteInt32(m_dataLength_); /* write the index (stage 1) array and the 16/32-bit data (stage 2) array */ if (reduceTo16Bits) { /* write 16-bit index values shifted right by UTRIE_INDEX_SHIFT, after adding indexLength */ for (int i = 0; i < m_indexLength_; i++) { int v = (m_index_[i] + m_indexLength_).TripleShift(Trie.IndexStage2Shift); dos.WriteChar(v); } /* write 16-bit data values */ for (int i = 0; i < m_dataLength_; i++) { int v = m_data_[i] & 0x0000ffff; dos.WriteChar(v); } } else { /* write 16-bit index values shifted right by UTRIE_INDEX_SHIFT */ for (int i = 0; i < m_indexLength_; i++) { int v = (m_index_[i]).TripleShift(Trie.IndexStage2Shift); dos.WriteChar(v); } /* write 32-bit data values */ for (int i = 0; i < m_dataLength_; i++) { dos.WriteInt32(m_data_[i]); } } return(length); }
/// <summary> /// Serializes the build table to an output stream. /// Compacts the build-time trie after all values are set, and then writes /// the serialized form onto an output stream. /// After this, this build-time Trie can only be serialized again and/or /// closed; no further values can be added. /// This function is the rough equivalent of utrie_seriaize() in ICU4C. /// </summary> /// /// <param name="os">the output stream to which the seriaized trie will be written.If nul, the function still returns the size of the serializedTrie.</param> /// <param name="reduceTo16Bits">If true, reduce the data size to 16 bits. The resultingserialized form can then be used to create a CharTrie.</param> /// <param name="datamanipulate">builder raw fold method implementation</param> /// <returns>the number of bytes written to the output stream.</returns> public int Serialize(Stream os, bool reduceTo16Bits, TrieBuilder.DataManipulate datamanipulate) { if (datamanipulate == null) { throw new ArgumentException("Parameters can not be null"); } // fold and compact if necessary, also checks that indexLength is // within limits if (!m_isCompacted_) { // compact once without overlap to improve folding Compact(false); // fold the supplementary part of the index array Fold(datamanipulate); // compact again with overlap for minimum data array length Compact(true); m_isCompacted_ = true; } // is dataLength within limits? int length; if (reduceTo16Bits) { length = m_dataLength_ + m_indexLength_; } else { length = m_dataLength_; } if (length >= IBM.ICU.Impl.TrieBuilder.MAX_DATA_LENGTH_) { throw new IndexOutOfRangeException("Data length too small".ToString()); } // struct UTrieHeader { // int32_t signature; // int32_t options (a bit field) // int32_t indexLength // int32_t dataLength length = IBM.ICU.Impl.Trie.HEADER_LENGTH_ + 2 * m_indexLength_; if (reduceTo16Bits) { length += 2 * m_dataLength_; } else { length += 4 * m_dataLength_; } if (os == null) { // No output stream. Just return the length of the serialized Trie, // in bytes. return(length); } DataOutputStream dos = new DataOutputStream(os); dos.WriteInt(IBM.ICU.Impl.Trie.HEADER_SIGNATURE_); int options = IBM.ICU.Impl.Trie.INDEX_STAGE_1_SHIFT_ | (IBM.ICU.Impl.Trie.INDEX_STAGE_2_SHIFT_ << IBM.ICU.Impl.Trie.HEADER_OPTIONS_INDEX_SHIFT_); if (!reduceTo16Bits) { options |= IBM.ICU.Impl.Trie.HEADER_OPTIONS_DATA_IS_32_BIT_; } if (m_isLatin1Linear_) { options |= IBM.ICU.Impl.Trie.HEADER_OPTIONS_LATIN1_IS_LINEAR_MASK_; } dos.WriteInt(options); dos.WriteInt(m_indexLength_); dos.WriteInt(m_dataLength_); /* * write the index (stage 1) array and the 16/32-bit data (stage 2) * array */ if (reduceTo16Bits) { /* * write 16-bit index values shifted right by UTRIE_INDEX_SHIFT, * after adding indexLength */ for (int i = 0; i < m_indexLength_; i++) { int v = (int)(((uint)(m_index_[i] + m_indexLength_)) >> IBM.ICU.Impl.Trie.INDEX_STAGE_2_SHIFT_); dos.WriteChar((char)v); } /* write 16-bit data values */ for (int i_0 = 0; i_0 < m_dataLength_; i_0++) { int v_1 = m_data_[i_0] & 0x0000ffff; dos.WriteChar((char)v_1); } } else { /* write 16-bit index values shifted right by UTRIE_INDEX_SHIFT */ for (int i_2 = 0; i_2 < m_indexLength_; i_2++) { int v_3 = (int)(((uint)(m_index_[i_2])) >> IBM.ICU.Impl.Trie.INDEX_STAGE_2_SHIFT_); dos.WriteChar((char)v_3); } /* write 32-bit data values */ for (int i_4 = 0; i_4 < m_dataLength_; i_4++) { dos.WriteInt(m_data_[i_4]); } } return(length); }
public void Run() { // Create a DataInputStream for communication; the client is using a DataOutputStream to write to us. var dInStream = new DataInputStream(socket.InputStream); // We'll also want a DataOutputStream, very briefly, to send our ACK character. var dOutStream = new DataOutputStream(socket.OutputStream); bool Handled; while (!StopToken.IsCancellationRequested) { Handled = false; // Get the next message try { var data = ReadString(dInStream).Split(onNEXT, 3); if (data.Length != 3) { Log.Debug(_tag, $"Data has <3 entries; [0] is {data.ElementAtOrDefault(0)}, [1] is {data.ElementAtOrDefault(1)}, [2] is {data.ElementAtOrDefault(2)}"); } var address = data.ElementAtOrDefault(0); var sender = data.ElementAtOrDefault(1); var message = data.ElementAtOrDefault(2); // If it's not for me, ignore it. Shouldn't happen in current code anyway. if (!address.IsOneOf(WiFiMessageReceiver.MyIPaddress, ALL)) { Log.Debug(_tag, $"Received \"{message}\" addressed to {address} (I'm {WiFiMessageReceiver.MyIPaddress}); ignoring it, but you should look into how it happened."); continue; } dOutStream.WriteChar(ACKchar); //if (server.DoACK && !message.StartsWith(ACK)) // server.ForwardTo(sender, "Server", $"{ACK}: relaying [{message}] from {sender}."); // Now handle the message contents if (message.StartsWith($"{INTRODUCING}{NEXT}")) { var newTeammate = TeamMember.FromIntroductionString(message); Log.Debug(_tag, $"Received introduction from {newTeammate.IPaddress}, giving their name ({newTeammate.Name}) and roles {newTeammate.Roles.Join()}. Adding to address book."); AddressBook.Add(newTeammate); } // If it doesn't fall into one of our special cases, handle it as a normal message. else { server.OnMessageReceived.Raise(new Message() { From = sender, To = address, Content = message }); //if (DoACK) SendMessage(sender, $"{ACK}: received [{message}] from {sender}."); } } catch (Java.IO.EOFException e) { Log.Debug(_tag, $"EOFException: {e.Message} ({e}). Logging & rethrowing."); throw e; //Log.Debug(_tag, $"EOFException: {e.Message} ({e}). Trying to reopen stream."); //dInStream.Dispose(); //dInStream = new DataInputStream(socket.InputStream); //Handled = true; //continue; } catch (Exception e) { if (e.InnerException != null && e.InnerException is Java.IO.EOFException) { Log.Debug(_tag, $"Wrapped EOFException: {e}. Logging & rethrowing. Status of socket is: IsInputShutdown? {socket.IsInputShutdown}. KeepAlive? {socket.KeepAlive}. Linger? {socket.SoLinger}. Timeout? {socket.SoTimeout}. ReuseAddress? {socket.ReuseAddress}. Channel? {socket.Channel}."); throw e.InnerException; //Log.Debug(_tag, $"Wrapped EOFException: {e}. Trying to reopen stream. Status of socket is: IsInputShutdown? {socket.IsInputShutdown}. KeepAlive? {socket.KeepAlive}. Linger? {socket.SoLinger}. Timeout? {socket.SoTimeout}. ReuseAddress? {socket.ReuseAddress}. Channel? {socket.Channel}."); //dInStream.Dispose(); //dInStream = new DataInputStream(socket.InputStream); ////Handled = true; //continue; } else { //Handled = false; throw e; } } finally { if (!Handled) { Log.Debug(_tag, $"ServerThread to {socket.InetAddress.CanonicalHostName} self-disrupted."); Stop(); } } } }