AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
CircularBuffer.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 
6 namespace HoloToolkit.Unity
7 {
11  public class CircularBuffer
12  {
13  public CircularBuffer(int size, bool allowOverwrite = false, int padding = 4)
14  {
15  data = new byte[size];
16  readWritePadding = padding;
17  this.allowOverwrite = allowOverwrite;
18  }
19 
20  public int TotalCapacity
21  {
22  get
23  {
24  return data.Length - readWritePadding;
25  }
26  }
27 
28  public int UsedCapacity
29  {
30  get
31  {
32  if (writeOffset >= readOffset)
33  {
34  return writeOffset - readOffset;
35  }
36  int firstChunk = data.Length - readOffset;
37  int secondChunk = writeOffset;
38  return firstChunk + secondChunk;
39  }
40  }
41 
42  public void Reset()
43  {
44  readOffset = 0;
45  writeOffset = 0;
46  }
47 
48  public int Write(Array src, int srcReadPosBytes, int byteCount)
49  {
50  int maxWritePos;
51  bool wrappedAround = writeOffset < readOffset;
52  if (!wrappedAround)
53  {
54  maxWritePos = (readOffset != 0 || allowOverwrite) ? data.Length : data.Length - readWritePadding;
55  }
56  else
57  {
58  maxWritePos = allowOverwrite ? data.Length : readOffset - readWritePadding;
59  }
60 
61  int chunkSize = Math.Min(byteCount, maxWritePos - writeOffset);
62  int writeEnd = writeOffset + chunkSize;
63  bool needToMoveReadOffset = wrappedAround ? writeEnd >= readOffset : (writeEnd == data.Length && readOffset == 0);
64  if (needToMoveReadOffset)
65  {
66  if (!allowOverwrite)
67  {
68  throw new Exception("Circular buffer logic error. Overwriting data.");
69  }
70  readOffset = (writeEnd + readWritePadding) % data.Length;
71  }
72 
73  Buffer.BlockCopy(src, srcReadPosBytes, data, writeOffset, chunkSize);
74  writeOffset = (writeOffset + chunkSize) % data.Length;
75 
76  int bytesWritten = chunkSize;
77  int remaining = byteCount - bytesWritten;
78  if (bytesWritten > 0 && remaining > 0)
79  {
80  bytesWritten += Write(src, srcReadPosBytes + chunkSize, remaining);
81  }
82 
83  return bytesWritten;
84  }
85 
86  public int Read(Array dst, int dstWritePosBytes, int byteCount)
87  {
88  if (readOffset == writeOffset)
89  {
90  return 0;
91  }
92 
93  int maxReadPos;
94  if (readOffset > writeOffset)
95  {
96  maxReadPos = data.Length;
97  }
98  else
99  {
100  maxReadPos = writeOffset;
101  }
102 
103  int chunkSize = Math.Min(byteCount, maxReadPos - readOffset);
104 
105  Buffer.BlockCopy(data, readOffset, dst, dstWritePosBytes, chunkSize);
106  readOffset = (readOffset + chunkSize) % data.Length;
107 
108  int bytesRead = chunkSize;
109  int remaining = byteCount - bytesRead;
110  if (bytesRead > 0 && remaining > 0)
111  {
112  bytesRead += Read(dst, dstWritePosBytes + bytesRead, remaining);
113  }
114 
115  return bytesRead;
116  }
117 
118  private byte[] data;
119  private int writeOffset;
120  private int readOffset;
121 
122  private readonly int readWritePadding;
123  private readonly bool allowOverwrite;
124  }
125 }
CircularBuffer(int size, bool allowOverwrite=false, int padding=4)
Helper class for transmitting data over network.
int Read(Array dst, int dstWritePosBytes, int byteCount)
int Write(Array src, int srcReadPosBytes, int byteCount)