/// <summary> /// Returns the byte size of the message. /// </summary> public override int Size() { if (!_dirtySize) { return(_cachedSize); } _cachedSize = 0; // Address. _cachedSize += StringOscData.EvaluateByteCount(_address); // Tags. _cachedSize++; // Prefix; _cachedSize += _argInfo.Count; // ASCII char tags. _cachedSize += 4 - (_cachedSize % 4); // Followed by at least one trailing zero, multiple of four bytes. // Data, already multiple of four bytes. int argCount = _argInfo.Count; for (int i = 0; i < argCount; i++) { _cachedSize += _argInfo[i].size; } return(_cachedSize); }
/// <summary> /// Set argument at specified index, expanding message capacity if necessary. /// </summary> public OscMessage Set(int index, string value) { OscArgInfo info = new OscArgInfo(OscConst.tagStringByte, StringOscData.EvaluateByteCount(value)); int dataStartIndex = AdaptiveSet(index, info); if (!StringOscData.TryWriteTo(value, _argData, ref dataStartIndex)) { Debug.Log(OscDebug.FailedWritingBytesWarning(this)); } return(this); }
public void Add(params object[] args) { // Adaptive Set info capacity. int infoStartIndex = _argInfo.Count; int newArgCount = infoStartIndex + args.Length; if (newArgCount > _argInfo.Capacity) { _argInfo.Capacity = newArgCount; } // Get info and evaluate data byte count. int newArgsByteCount = 0; foreach (object arg in args) { byte tagByte = OscConverter.ToTagByte(arg); int argByteCount = 0; switch (tagByte) { case OscConst.tagFloatByte: case OscConst.tagIntByte: case OscConst.tagCharByte: case OscConst.tagColorByte: case OscConst.tagMidiByte: argByteCount = 4; break; case OscConst.tagDoubleByte: case OscConst.tagLongByte: case OscConst.tagTimetagByte: argByteCount = 8; break; case OscConst.tagStringByte: argByteCount = StringOscData.EvaluateByteCount((string)arg); break; case OscConst.tagBlobByte: argByteCount = BlobOscData.EvaluateByteCount((byte[])arg); break; } _argInfo.Add(new OscArgInfo(tagByte, argByteCount)); newArgsByteCount += argByteCount; } // AdaptiveSet data capacity. int totalArgsByteCount = _argData.Count + newArgsByteCount; if (totalArgsByteCount > _argData.Capacity) { _argData.Capacity = totalArgsByteCount; } // Store arguments directly as bytes. int i = infoStartIndex; foreach (object arg in args) { switch (_argInfo[i++].tagByte) { case OscConst.tagFloatByte: new FourByteOscData((float)arg).AddTo(_argData); break; case OscConst.tagIntByte: new FourByteOscData((int)arg).AddTo(_argData); break; case OscConst.tagCharByte: new FourByteOscData((char)arg).AddTo(_argData); break; case OscConst.tagColorByte: new FourByteOscData((Color32)arg).AddTo(_argData); break; case OscConst.tagMidiByte: new FourByteOscData((OscMidiMessage)arg).AddTo(_argData); break; case OscConst.tagDoubleByte: new EightByteOscData((double)arg).AddTo(_argData); break; case OscConst.tagLongByte: new EightByteOscData((long)arg).AddTo(_argData); break; case OscConst.tagTimetagByte: new EightByteOscData((OscTimeTag)arg).AddTo(_argData); break; case OscConst.tagStringByte: StringOscData.AddTo((string)arg, _argData); break; case OscConst.tagBlobByte: BlobOscData.AddTo((byte[])arg, _argData); break; case OscConst.tagUnsupportedByte: // For unsupported tags, we don't attemt to store any data. But we warn the user. Debug.LogWarning("Type " + arg.GetType() + " is not supported.\n"); // TODO warnings should be optional. break; } } }
// Undocumented on purpose. public static bool TryReadFrom(byte[] data, ref int index, int size, ref OscMessage message) { int beginIndex = index; // If we are not provided with a message, then read the lossy hash and try reuse from the pool. if (message == null) { int hash = OscStringHash.Pack(data, index); message = OscPool.GetMessage(hash); } else { if (message._argInfo.Count > 0) { message.Clear(); // Ensure that arguments are cleared. } } // Address. string address = message._address; if (!StringOscData.TryReadFrom(data, ref index, ref address)) { Debug.Log(OscDebug.FailedReadingBytesWarning(message)); return(false); } message._address = address; // Tag prefix. if (data[index] != OscConst.tagPrefixByte) { StringBuilder sb = OscDebug.BuildText(message); sb.Append("Read failed. Tag prefix missing.\n"); Debug.LogWarning(sb.ToString()); return(false); } index++; // Argument tags. for (int i = index; i < data.Length && data[i] != 0; i++) { message._argInfo.Add(new OscArgInfo(data[i], 0)); } index += message._argInfo.Count; // Followed by at least one trailing zero, multiple of four bytes. index += 4 - (index % 4); //Debug.Log( "READ: Args data start index: " + index ); // Argument data info. int argDataByteCount = 0; for (int i = 0; i < message._argInfo.Count; i++) { byte tagByte = message._argInfo[i].tagByte; int argByteCount = 0; switch (tagByte) { case OscConst.tagNullByte: case OscConst.tagImpulseByte: case OscConst.tagTrueByte: case OscConst.tagFalseByte: break; case OscConst.tagFloatByte: case OscConst.tagIntByte: case OscConst.tagCharByte: case OscConst.tagColorByte: case OscConst.tagMidiByte: argByteCount = 4; break; case OscConst.tagDoubleByte: case OscConst.tagLongByte: case OscConst.tagTimetagByte: argByteCount = 8; break; case OscConst.tagStringByte: case OscConst.tagSymbolByte: argByteCount = StringOscData.EvaluateByteCount(data, index + argDataByteCount); break; case OscConst.tagBlobByte: BlobOscData.TryEvaluateByteCount(data, index + argDataByteCount, out argByteCount); break; default: StringBuilder sb = OscDebug.BuildText(message); sb.Append("Read failed. Tag '"); sb.Append((char)tagByte); sb.Append("' is not supported\n"); Debug.LogWarning(sb.ToString()); return(false); } message._argInfo[i] = new OscArgInfo(tagByte, argByteCount); //Debug.Log( "i; " + i + ", info: " + message._argInfo[i] ); argDataByteCount += argByteCount; } // AdaptiveSet data list. if (message._argData.Capacity < argDataByteCount) { message._argData.Capacity = argDataByteCount; } // Read data. for (int i = 0; i < argDataByteCount; i++) { message._argData.Add(data[index++]); } // Cache byte count. message._cachedSize = index - beginIndex; message._dirtySize = false; return(true); }