1
+ /*******************************************************************************
2
+ * HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5
+ * the License. You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11
+ * specific language governing permissions and limitations under the License.
12
+ *******************************************************************************/
13
+
14
+ package org .hpccsystems .dfs .client ;
15
+
16
+ import java .io .IOException ;
17
+
18
+ public class CircularByteBuffer
19
+ {
20
+ private final byte [] buffer ;
21
+ private int readPos = 0 ;
22
+ private int writePos = 0 ;
23
+ private int markPos = 0 ;
24
+ private int bytesReadAfterMark = 0 ;
25
+ private int currentNumberOfBytes = 0 ;
26
+
27
+ public CircularByteBuffer (int bufferSize )
28
+ {
29
+ buffer = new byte [bufferSize ];
30
+ }
31
+
32
+ public int getCurrentNumberOfBytes ()
33
+ {
34
+ // We only adjust for the mark internally and when providing information about available space
35
+ return currentNumberOfBytes ;
36
+ }
37
+
38
+ public boolean hasSpace ()
39
+ {
40
+ return getSpace () > 0 ;
41
+ }
42
+
43
+ public int getSpace ()
44
+ {
45
+ int adjustedByteCount = currentNumberOfBytes ;
46
+ if (markPos >= 0 )
47
+ {
48
+ adjustedByteCount += bytesReadAfterMark ;
49
+ }
50
+
51
+ return buffer .length - adjustedByteCount ;
52
+ }
53
+
54
+ public int getContiguousSpace ()
55
+ {
56
+ if (!hasSpace ())
57
+ {
58
+ return 0 ;
59
+ }
60
+
61
+ // If we have a marked position we don't want to allow that space to be written to until after reset has been called
62
+ int rPos = readPos ;
63
+ if (markPos >= 0 )
64
+ {
65
+ rPos = markPos ;
66
+ }
67
+
68
+ if (writePos >= rPos )
69
+ {
70
+ return buffer .length - writePos ;
71
+ }
72
+ else
73
+ {
74
+ return rPos - writePos ;
75
+ }
76
+ }
77
+
78
+ public int getWriteOffset ()
79
+ {
80
+ return writePos ;
81
+ }
82
+
83
+ public int incrementWriteOffset (int increment )
84
+ {
85
+ int maxIncrement = buffer .length - writePos ;
86
+ increment = Math .min (increment , maxIncrement );
87
+
88
+ writePos += increment ;
89
+ if (writePos >= buffer .length )
90
+ {
91
+ writePos = 0 ;
92
+ }
93
+
94
+ currentNumberOfBytes += increment ;
95
+ return increment ;
96
+ }
97
+
98
+ public void add (final byte [] targetBuffer , final int offset , final int length ) throws IOException
99
+ {
100
+ if (currentNumberOfBytes + length > buffer .length )
101
+ {
102
+ throw new IOException ("Not enough space available" );
103
+ }
104
+
105
+ for (int i = 0 ; i < length ; i ++)
106
+ {
107
+ buffer [writePos ] = targetBuffer [offset + i ];
108
+ if (++writePos == buffer .length )
109
+ {
110
+ writePos = 0 ;
111
+ }
112
+ }
113
+ currentNumberOfBytes += length ;
114
+ }
115
+
116
+ public byte read () throws IOException
117
+ {
118
+ if (currentNumberOfBytes <= 0 )
119
+ {
120
+ throw new IOException ("No bytes available to read" );
121
+ }
122
+
123
+ byte b = buffer [readPos ];
124
+ currentNumberOfBytes --;
125
+
126
+ if (markPos >= 0 )
127
+ {
128
+ bytesReadAfterMark ++;
129
+ }
130
+
131
+ readPos ++;
132
+ if (readPos >= buffer .length )
133
+ {
134
+ readPos = 0 ;
135
+ }
136
+
137
+ return b ;
138
+ }
139
+
140
+ public void read (final byte [] targetBuffer , final int targetOffset , final int length ) throws IOException
141
+ {
142
+ if (length > currentNumberOfBytes )
143
+ {
144
+ throw new IOException ("Not enough bytes available to read" );
145
+ }
146
+
147
+ if (readPos + length <= buffer .length )
148
+ {
149
+ System .arraycopy (buffer , readPos , targetBuffer , targetOffset , length );
150
+ }
151
+ else
152
+ {
153
+ int firstCopyLength = buffer .length - readPos ;
154
+ System .arraycopy (buffer , readPos , targetBuffer , targetOffset , firstCopyLength );
155
+ System .arraycopy (buffer , 0 , targetBuffer , targetOffset + firstCopyLength , length - firstCopyLength );
156
+ }
157
+
158
+ readPos += length ;
159
+ if (readPos >= buffer .length )
160
+ {
161
+ readPos -= buffer .length ;
162
+ }
163
+
164
+ currentNumberOfBytes -= length ;
165
+ if (markPos >= 0 )
166
+ {
167
+ bytesReadAfterMark += length ;
168
+ }
169
+ }
170
+
171
+ public byte [] getInternalBuffer ()
172
+ {
173
+ return buffer ;
174
+ }
175
+
176
+ public void mark (int readLim ) throws IllegalArgumentException
177
+ {
178
+ if (readLim > buffer .length )
179
+ {
180
+ throw new IllegalArgumentException ("Read limit exceeds available bytes" );
181
+ }
182
+
183
+ markPos = readPos ;
184
+ bytesReadAfterMark = 0 ;
185
+ }
186
+
187
+ public void reset ()
188
+ {
189
+ if (markPos < 0 )
190
+ {
191
+ return ;
192
+ }
193
+
194
+ currentNumberOfBytes += bytesReadAfterMark ;
195
+
196
+ readPos = markPos ;
197
+ markPos = -1 ;
198
+ bytesReadAfterMark = 0 ;
199
+ }
200
+
201
+ public long skip (long n ) throws IOException
202
+ {
203
+ if (n > currentNumberOfBytes )
204
+ {
205
+ throw new IOException ("Not enough bytes available to skip" );
206
+ }
207
+
208
+ readPos += n ;
209
+ if (readPos >= buffer .length )
210
+ {
211
+ readPos -= buffer .length ;
212
+ }
213
+
214
+ currentNumberOfBytes -= n ;
215
+ return n ;
216
+ }
217
+ };
0 commit comments