forked from LucHeart/CoreOSC-UTF8-ASYNC
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOscPacketUtils.cs
More file actions
166 lines (137 loc) · 4.82 KB
/
Copy pathOscPacketUtils.cs
File metadata and controls
166 lines (137 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
using System;
using System.Buffers.Binary;
using System.Text;
namespace LucHeart.CoreOSC;
public static class OscPacketUtils
{
#region Get arguments from byte array
public const byte DividerChar = 44;
public static string GetAddress(ReadOnlySpan<byte> msg, out int index)
{
index = msg.IndexOf(DividerChar);
if (index == -1) throw new Exception("Could not get address from data");
var address = Encoding.ASCII.GetString(msg[..index]);
return address.Replace("\0", "");
}
public static ReadOnlySpan<char> GetTypes(ReadOnlySpan<byte> msg, int index)
{
var i = index + 4;
for (; i <= msg.Length; i += 4)
{
if (msg[i - 1] != 0) continue;
var charSet = msg[index..i];
var newSpan = new char[Encoding.ASCII.GetMaxCharCount(charSet.Length)].AsSpan();
Encoding.ASCII.GetChars(charSet, newSpan);
return newSpan;
}
throw new Exception("No null terminator after type string");
}
public static int GetInt(ReadOnlySpan<byte> msg, int index) =>
BinaryPrimitives.ReadInt32BigEndian(msg.Slice(index, 4));
public static float GetFloat(Span<byte> msg, int index) => BitConverter.ToSingle(msg.ReverseSlice(index, 4));
public static string GetString(ReadOnlySpan<byte> msg, int index, out int newIndex)
{
var i = index + 4;
for (; i - 1 < msg.Length; i += 4)
{
if (msg[i - 1] != 0) continue;
newIndex = i;
return Encoding.UTF8.GetString(msg[index..i]).Replace("\0", "");
}
throw new Exception("No null terminator after type string");
}
public static ReadOnlySpan<byte> GetBlob(ReadOnlySpan<byte> msg, int index)
{
var size = GetInt(msg, index);
return msg.Slice(index + 4, size);
}
public static ulong GetULong(ReadOnlySpan<byte> msg, int index) =>
BinaryPrimitives.ReadUInt64BigEndian(msg.Slice(index, 8));
public static long GetLong(ReadOnlySpan<byte> msg, int index) =>
BinaryPrimitives.ReadInt64BigEndian(msg.Slice(index, 8));
public static double GetDouble(Span<byte> msg, int index) => BitConverter.ToDouble(msg.ReverseSlice(index, 8));
public static char GetChar(ReadOnlySpan<byte> msg, int index) => (char)msg[index + 3];
public static RGBA GetRgba(ReadOnlySpan<byte> msg, int index) =>
new(msg[index], msg[index + 1], msg[index + 2], msg[index + 3]);
public static Midi GetMidi(ReadOnlySpan<byte> msg, int index) =>
new(msg[index], msg[index + 1], msg[index + 2], msg[index + 3]);
#endregion Get arguments from byte array
#region Create byte arrays for arguments
public static byte[] SetInt(int value)
{
var output = new byte[4];
BinaryPrimitives.WriteInt32BigEndian(output, value);
return output;
}
public static byte[] SetFloat(float value)
{
// ReSharper disable once RedundantAssignment
var output = new byte[4];
#if NETSTANDARD2_1
var rev = BitConverter.GetBytes(value);
output[0] = rev[3];
output[1] = rev[2];
output[2] = rev[1];
output[3] = rev[0];
# else
BinaryPrimitives.WriteSingleBigEndian(output, value);
#endif
return output;
}
public static byte[] SetString(string value)
{
var bytes = Encoding.UTF8.GetBytes(value);
var msg = new byte[(bytes.Length / 4 + 1) * 4];
bytes.CopyTo(msg, 0);
return msg;
}
public static byte[] SetBlob(byte[] value)
{
var len = value.Length + 4;
len += 4 - len % 4;
var msg = new byte[len];
BinaryPrimitives.WriteInt32BigEndian(msg, value.Length);
value.CopyTo(msg, 4);
return msg;
}
public static byte[] SetLong(long value)
{
var output = new byte[8];
BinaryPrimitives.WriteInt64BigEndian(output, value);
return output;
}
public static byte[] SetULong(ulong value)
{
var output = new byte[8];
BinaryPrimitives.WriteUInt64BigEndian(output, value);
return output;
}
public static byte[] SetDouble(double value)
{
var output = new byte[8];
#if NETSTANDARD2_1
var rev = BitConverter.GetBytes(value);
output[0] = rev[7];
output[1] = rev[6];
output[2] = rev[5];
output[3] = rev[4];
output[4] = rev[3];
output[5] = rev[2];
output[6] = rev[1];
output[7] = rev[0];
#else
BinaryPrimitives.WriteDoubleBigEndian(output, value);
#endif
return output;
}
public static byte[] SetChar(char value)
{
var output = new byte[4];
output[0] = 0;
output[1] = 0;
output[2] = 0;
output[3] = (byte)value;
return output;
}
#endregion Create byte arrays for arguments
}