I'm dealing with a COM port application and we have a defined variable-length packet structure that I'm talking to a micro-controller with. The packet has delimiters for the start and stop bytes. The trouble is that sometimes the read buffer can contain extraneous characters. It seems like I'll always get the whole packet, just some extra chatter before/after the actual data. So I have a buffer that I append data to whenever new data is received from the COM port. What is the best way to search this buffer for any possible occurrences of my packet? For example:
Say my packet delimiter is 0xFF
and I have an array as such
{ 0x00, 0xFF, 0x02, 0xDA, 0xFF, 0x55, 0xFF, 0x04 }
How can I create a function/LINQ-statment that returns all subarrays that start and end with the delimiter (almost like a sliding-correlator with wildcards)?
The sample would return the following 3 arrays:
{0xFF, 0x02, 0xDA, 0xFF}, {0xFF, 0x55, 0xFF}, and
{0xFF, 0x02, 0xDA, 0xFF, 0x55, 0xFF}
You could do this using a Linq aggregator, but it's much less straightforward than the other solutions suggested here, also had to add a special case to cover extending already completed arrays as you suggested above.
While Trystan's answer is technically correct, he's making lots of copies of the original array all at once. If the starting array is large and has a bunch of delimiters, that gets huge quickly. This approach avoids the massive memory consumption by using only the original array and an array for the current segment being evaluated.
Can be used as such:
I wouldn't try to do this with linq so here's a regular method that returns the same output as you wanted.
If it must be an in-place lambda expression, then just change the first line to
(byte[] array, byte delimeter) =>
(without the method modifiers and name) and call it that way.Here's how you can do this using LINQ ...
Or using indexes:
Although the delimiter structure seems a bit vague, I would not use linq and do something like below (no extensive tests performed). It will return all subsets (of bytes surrounded by the delimiter), without including the delimiter (it's a given anyway, why include it?). It also does not return the union of the results, but that can always be assembled manually.
If you really want to use LINQ, this should work quite fast (even if not as fast as a good-old for loop):