-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathICodec.cs
204 lines (191 loc) · 9 KB
/
ICodec.cs
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
using System;
using System.Linq;
using System.IO;
using System.Numerics;
namespace Datamodel.Codecs
{
/// <summary>
/// Defines methods for the encoding and decoding of <see cref="Datamodel"/> objects. Codecs are registered with <see cref="Datamodel.RegisterCodec"/>.
/// </summary>
/// <remarks>A new ICodec is instantiated for every encode/decode operation.</remarks>
/// <seealso cref="CodecUtilities"/>
public interface ICodec
{
/// <summary>
/// Encodes a <see cref="Datamodel"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="dm">The Datamodel to encode.</param>
/// <param name="encoding_version">The encoding version to use.</param>
/// <param name="stream">The output stream.</param>
void Encode(Datamodel dm, int encoding_version, Stream stream);
/// <summary>
/// Decodes a <see cref="Datamodel"/> from a <see cref="Stream"/>.
/// </summary>
/// <param name="encoding_version">The encoding version that this stream uses.</param>
/// <param name="format">The format of the Datamodel.</param>
/// <param name="format_version">The format version of the Datamodel.</param>
/// <param name="stream">The input stream. Its position will always be 0. Do not dispose.</param>
/// <param name="defer_mode">The deferred loading mode specified by the caller. Only relevant to implementers of <see cref="IDeferredAttributeCodec"/></param>
/// <returns></returns>
Datamodel Decode(int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode);
}
/// <summary>
/// Defines methods for the deferred loading of <see cref="Attribute"/> values.
/// </summary>
/// <remarks>
/// <para>Implementers must still load all elements and Attribute names. Only Attribute values can be streamed.</para>
/// <para>IDeferredAttributeCodec objects will be attached to their host Datamodel for the duration of its life.</para>
/// </remarks>
/// <seealso cref="CodecUtilities"/>
public interface IDeferredAttributeCodec : ICodec
{
/// <summary>
/// Called when an unloaded <see cref="Attribute"/> is accessed.
/// </summary>
/// <param name="dm">The <see cref="Datamodel"/> to which the Attribute belongs.</param>
/// <param name="offset">The offset at which the Attribute begins in the source <see cref="Stream"/>.</param>
/// <returns>The Attribute's value.</returns>
object DeferredDecodeAttribute(Datamodel dm, long offset);
}
/// <summary>
/// Values which instruct <see cref="IDeferredAttributeCodec"/> implementers on how to use deferred Attribute reading.
/// </summary>
public enum DeferredMode
{
/// <summary>
/// The codec decides whether to defer attribute loading.
/// </summary>
Automatic,
/// <summary>
/// The codec loads all attributes immediately.
/// </summary>
Disabled
}
/// <summary>
/// Helper methods for <see cref="ICodec"/> implementers.
/// </summary>
public static class CodecUtilities
{
/// <summary>
/// Standard DMX header with CLR-style variable tokens.
/// </summary>
public const string HeaderPattern = "<!-- dmx encoding {0} {1} format {2} {3} -->";
/// <summary>
/// Standard DMX header as a regular expression pattern.
/// </summary>
public const string HeaderPattern_Regex = "<!-- dmx encoding (\\S+) ([0-9]+) format (\\S+) ([0-9]+) -->";
//public const string HeaderPattern_Proto2 = "<!-- DMXVersion binary_v{0} -->";
/// <summary>
/// Creates a <see cref="List<T>"/> for the given Type with the given starting size.
/// </summary>
public static System.Collections.IList MakeList(Type t, int count)
{
if (t == typeof(Element))
return new ElementArray(count);
if (t == typeof(int))
return new IntArray(count);
if (t == typeof(float))
return new FloatArray(count);
if (t == typeof(bool))
return new BoolArray(count);
if (t == typeof(string))
return new StringArray(count);
if (t == typeof(byte[]))
return new BinaryArray(count);
if (t == typeof(TimeSpan))
return new TimeSpanArray(count);
if (t == typeof(System.Drawing.Color))
return new ColorArray(count);
if (t == typeof(Vector2))
return new Vector2Array(count);
if (t == typeof(Vector3))
return new Vector3Array(count);
if (t == typeof(Vector4))
return new Vector4Array(count);
if (t == typeof(Quaternion))
return new QuaternionArray(count);
if (t == typeof(Matrix4x4))
return new MatrixArray(count);
if (t == typeof(byte))
return new ByteArray(count);
if (t == typeof(UInt64))
return new UInt64Array(count);
throw new ArgumentException("Unrecognised Type.");
}
/// <summary>
/// Creates a <see cref="List<T>"/> for the given Type, copying items the given IEnumerable
/// </summary>
public static System.Collections.IList MakeList(Type t, System.Collections.IEnumerable source)
{
if (t == typeof(Element))
return new ElementArray(source.Cast<Element>());
if (t == typeof(int))
return new IntArray(source.Cast<int>());
if (t == typeof(float))
return new FloatArray(source.Cast<float>());
if (t == typeof(bool))
return new BoolArray(source.Cast<bool>());
if (t == typeof(string))
return new StringArray(source.Cast<string>());
if (t == typeof(byte[]))
return new BinaryArray(source.Cast<byte[]>());
if (t == typeof(TimeSpan))
return new TimeSpanArray(source.Cast<TimeSpan>());
if (t == typeof(System.Drawing.Color))
return new ColorArray(source.Cast<System.Drawing.Color>());
if (t == typeof(Vector2))
return new Vector2Array(source.Cast<Vector2>());
if (t == typeof(Vector3))
return new Vector3Array(source.Cast<Vector3>());
if (t == typeof(Vector4))
return new Vector4Array(source.Cast<Vector4>());
if (t == typeof(Quaternion))
return new QuaternionArray(source.Cast<Quaternion>());
if (t == typeof(Matrix4x4))
return new MatrixArray(source.Cast<Matrix4x4>());
if (t == typeof(byte))
return new ByteArray(source.Cast<byte>());
if (t == typeof(UInt64))
return new UInt64Array(source.Cast<UInt64>());
throw new ArgumentException("Unrecognised Type.");
}
/// <summary>
/// Creates a new attribute on an <see cref="Element"/>. This method is intended for <see cref="ICodec"/> implementers and should not be directly called from any other code.
/// </summary>
/// <param name="elem">The Element to add to.</param>
/// <param name="key">The name of the attribute. Must be unique on the Element.</param>
/// <param name="defer_offset">The location in the encoded DMX stream at which this Attribute's value can be found.</param>
public static void AddDeferredAttribute(Element elem, string key, long offset)
{
if (offset <= 0) throw new ArgumentOutOfRangeException("offset", "Address must be greater than 0.");
elem.Add(key, offset);
}
}
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public sealed class CodecFormatAttribute : System.Attribute
{
/// <summary>
/// Specifies a Datamodel encoding name and some versions that a class handles.
/// </summary>
/// <param name="name">The encoding name that the codec handles.</param>
/// <param name="versions">The encoding version(s) that the codec handles.</param>
public CodecFormatAttribute(string name, params int[] versions)
{
Name = name;
Versions = versions;
}
/// <summary>
/// Specifies a Datamodel encoding name and version that a class handles.
/// </summary>
/// <remarks>This constructor is CLS-compliant.</remarks>
/// <param name="name">The encoding name that the codec handles.</param>
/// <param name="version">An encoding version that the codec handles.</param>
public CodecFormatAttribute(string name, int version)
{
Name = name;
Versions = new int[] { version };
}
public string Name { get; private set; }
public int[] Versions { get; private set; }
}
}