C# Client Library
A C# Client Library for the AnalyzeRe REST API
Loading...
Searching...
No Matches
BinaryYELTConverter.cs
Go to the documentation of this file.
1using System;
2using System.Globalization;
3using System.Text;
5
7{
9 [Obsolete("The binary YELT format and related options will be deprecated in the near future." +
10 "We encourage you to upload your YELT data as human-readable CSV.")]
11 public class BinaryYELTConverter : ProducerConsumerBuffer<BufferedBytes>
12 {
14 public static readonly Encoding DEFAULT_ENCODING = Encoding.UTF8;
15
16 private const NumberStyles IntParseStyle = NumberStyles.None;
17
18 private const NumberStyles DoubleParseStyle =
19 NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
20
21 private readonly CultureInfo _parseCulture = CultureInfo.InvariantCulture;
22 private static readonly char[] RowSeparators = { '\r', '\n' };
23 private readonly StringSplitter _rowSplitter = new StringSplitter(1000);
24 private readonly StringSplitter _binarySplitter = new StringSplitter(4);
25
27 public Encoding Encoding { get; }
28
29 private readonly IProducerConsumerBuffer<BufferedBytes> _source;
30
32 private string _leftOver = null;
33
42 int max_queue_size = 3, Encoding encoding = null)
43 : base(max_queue_size)
44 {
45 Encoding = encoding ?? DEFAULT_ENCODING;
46 _source = source;
47 }
48
50 protected override void OnStart()
51 {
52 base.OnStart();
53 // Start the source producer if it hasn't already started.
54 if (!_source.IsRunning)
55 _source.Start(Cancellation.Token);
56 }
57
60 protected override bool IsProducerFinished() =>
61 !_source.CanTake && _leftOver == null;
62
66 protected override bool TryProduceNext(out BufferedBytes next)
67 {
68 BufferedBytes buffer = _source.TryTake(out bool success, Cancellation.Token);
69 next = new BufferedBytes();
70 // If we've reached the end of the source file, take note
71 bool end_of_file = !_source.CanTake;
72 if (!success && (!end_of_file || _leftOver == null))
73 return false;
74 // Start with any characters left over from the last byte array, then add new stuff
75 string decoded = _leftOver;
76 if (success)
77 decoded += Encoding.GetString(buffer.Bytes, 0, buffer.LengthFilled);
78 // Get the number of rows.
79 int row_count = _rowSplitter.SafeSplit(decoded, RowSeparators, StringSplitOptions.RemoveEmptyEntries);
80 string[] rows = _rowSplitter.buffer;
81 // If we aren't at the end of file, ignore the last row, it's probably incomplete.
82 _leftOver = end_of_file ? null : rows[row_count - 1];
83 // Need to check if the last char was a newline, since split would ignore it
84 if (decoded[decoded.Length - 1] == '\n' && !end_of_file)
85 _leftOver += '\n';
86 if (!end_of_file) row_count -= 1;
87
88 // Allocate enough bytes to hold all but the last row (unless we're at the end)
89 next.Bytes = new byte[row_count * 32];
90 int byte_offset = 0, rows_skipped = 0, i = 0;
91 try
92 {
93 // Parse the rows as quick as we can, with no validation
94 for (i = 0; i < row_count; i++)
95 {
96 if (rows[i].Length == 0)
97 {
98 rows_skipped++;
99 continue;
100 }
101 _binarySplitter.Split(rows[i], ',');
102 string[] items = _binarySplitter.buffer;
103
104 CopyAsBytes(next.Bytes, ref byte_offset,
105 UInt64.Parse(items[1], IntParseStyle, _parseCulture), //Trial ID
106 UInt64.Parse(items[0], IntParseStyle, _parseCulture), //Event ID
107 Double.Parse(items[2], DoubleParseStyle, _parseCulture), //Day / Sequence
108 Double.Parse(items[3], DoubleParseStyle, _parseCulture)); //Loss
109 }
110 }
111 catch (Exception ex)
112 {
113 throw new ArgumentException("There was an error parsing the contents of " +
114 "the YELT row " + (i + 1) + " containing \"" + rows[i] +
115 "\". Expected \"UInt64,UInt64,Double,Double\". Error: " + ex.Message, ex);
116 }
117 // We always fill the whole byte array, minus allocated rows that were skipped.
118 next.LengthFilled = next.Bytes.Length - (rows_skipped * 32);
119 next.TotalBytesRead = buffer.TotalBytesRead;
120 return true;
121 }
122
130 public static void CopyAsBytes(byte[] destination, ref int offset, ulong trialId, ulong eventId,
131 double sequence, double loss)
132 {
133 BitConverter.GetBytes(trialId).CopyTo(destination, offset);
134 offset += 8;
135 BitConverter.GetBytes(eventId).CopyTo(destination, offset);
136 offset += 8;
137 BitConverter.GetBytes(sequence).CopyTo(destination, offset);
138 offset += 8;
139 BitConverter.GetBytes(loss).CopyTo(destination, offset);
140 offset += 8;
141 }
142 }
143}
Converts a YELT CSV data into a specified format.
override void OnStart()
Invoked before the producer thread is started.
BinaryYELTConverter(IProducerConsumerBuffer< BufferedBytes > source, int max_queue_size=3, Encoding encoding=null)
Construct a buffered bytes of binary YELT from other buffered bytes.
Encoding Encoding
The encoding to use when producing the strings.
override bool TryProduceNext(out BufferedBytes next)
The method which asynchronously produces items.
static void CopyAsBytes(byte[] destination, ref int offset, ulong trialId, ulong eventId, double sequence, double loss)
Copy the values of a YELT row into an array as bytes.
override bool IsProducerFinished()
Indicates whether it can produce more items.
static readonly Encoding DEFAULT_ENCODING
The default encoding used if none is supplied at construction.
Base class that consumes from a source asynchronously and produces a queue of some other resource to ...
CancellationTokenSource Cancellation
Can be used to cancel the buffering process.
A high performance string splitter https://github.com/meikeric/String.Split/blob/master/Split....
Interface for a class that consumes from a source asynchronously and produces a queue of some other r...
byte[] Bytes
The buffer of bytes filled.
int LengthFilled
The actual length of bytes, which may be shorter.
long TotalBytesRead
The total number of bytes read by the source producer as of this buffer i.e. The change in the source...
The structure containing an array of bytes and integer indicating the number of bytes in the array th...