View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.file;
21  
22  import io.netty.buffer.ByteBuf;
23  import io.netty.buffer.Unpooled;
24  import org.waarp.common.utility.WaarpNettyUtil;
25  
26  /**
27   * Main object implementing Data Block whaveter the mode, type, structure used.
28   */
29  public class DataBlock {
30    private static final int EOR = 128;
31  
32    private static final int EOF = 64;
33  
34    private static final int ERROR = 32;
35  
36    private static final int RESTART = 16;
37  
38    /**
39     * Descriptor
40     */
41    private int descriptor;
42  
43    /**
44     * Byte Count
45     */
46    private int byteCount = -1;
47  
48    /**
49     * Markers
50     */
51    private int[] markers;
52  
53    /**
54     * Byte Array
55     */
56    private byte[] block;
57    private ByteBuf blockBuf;
58    private int offsetBuf;
59  
60    /**
61     * is EOF
62     */
63    private boolean isEOF;
64  
65    /**
66     * is EOR
67     */
68    private boolean isEOR;
69  
70    /**
71     * is in ERROR (should not be used)
72     */
73    private boolean isERROR;
74  
75    /**
76     * is a MARKER RESTART
77     */
78    private boolean isRESTART;
79  
80    /**
81     * Create a simple and empty DataBlock
82     */
83    public DataBlock() {
84      // Empty
85    }
86  
87    /**
88     * @return the block
89     *
90     * @deprecated method, prefer getByteBlock()
91     */
92    @Deprecated
93    public final ByteBuf getBlock() {
94      if (blockBuf == null) {
95        blockBuf = Unpooled.wrappedBuffer(block);
96        offsetBuf = 0;
97      }
98      return blockBuf;
99    }
100 
101   /**
102    * @return the block
103    */
104   public final byte[] getByteBlock() {
105     return block;
106   }
107 
108   /**
109    * @return the offset of the ByteBlock
110    */
111   public final int getOffset() {
112     return offsetBuf;
113   }
114 
115   /**
116    * Increase the offset position
117    *
118    * @param offset
119    */
120   public final void addOffset(final int offset) {
121     offsetBuf += offset;
122   }
123 
124   /**
125    * Set the block and the byte count according to the block
126    *
127    * @param block the block to set
128    */
129   public final void setBlock(final ByteBuf block) {
130     if (isRESTART) {
131       this.block = null;
132       markers = new int[6];
133       for (int i = 0; i < 6; i++) {
134         markers[i] = block.readByte();
135       }
136       byteCount = 6;
137       return;
138     }
139     byteCount = block.readableBytes();
140     this.block = new byte[byteCount];
141     offsetBuf = 0;
142     if (blockBuf != null) {
143       WaarpNettyUtil.release(blockBuf);
144       blockBuf = null;
145     }
146     block.readBytes(this.block);
147     WaarpNettyUtil.release(block);
148   }
149 
150   /**
151    * Set the block and the byte count according to the block
152    *
153    * @param block the block to set
154    */
155   public final void setBlock(final byte[] block) {
156     setBlock(block, block != null? block.length : 0);
157   }
158 
159   /**
160    * Set the block and the byte count
161    *
162    * @param block the block to set
163    * @param size the real size to set
164    */
165   public final void setBlock(final byte[] block, final int size) {
166     if (isRESTART) {
167       this.block = null;
168       markers = new int[6];
169       if (block == null) {
170         for (int i = 0; i < 6; i++) {
171           markers[i] = 0;
172         }
173       } else {
174         for (int i = 0; i < 6; i++) {
175           markers[i] = block[i];
176         }
177       }
178       byteCount = 6;
179       return;
180     }
181     this.block = block;
182     if (this.block == null) {
183       byteCount = 0;
184     } else {
185       byteCount = size;
186     }
187     if (blockBuf != null) {
188       WaarpNettyUtil.release(blockBuf);
189       blockBuf = null;
190     }
191     offsetBuf = 0;
192   }
193 
194   /**
195    * @return the byteCount
196    */
197   public final int getByteCount() {
198     return byteCount - offsetBuf;
199   }
200 
201   /**
202    * @param byteCount the byteCount to set
203    */
204   public final void setByteCount(final int byteCount) {
205     this.byteCount = byteCount;
206   }
207 
208   /**
209    * @param upper upper byte of the 2 bytes length
210    * @param lower lower byte of the 2 bytes length
211    */
212   public final void setByteCount(final byte upper, final byte lower) {
213     byteCount = upper << 8 | (lower & 0xFF);
214   }
215 
216   /**
217    * @return the Upper byte of the byte count
218    */
219   public final byte getByteCountUpper() {
220     return (byte) (byteCount >> 8 & 0xFF);
221   }
222 
223   /**
224    * @return the Lower byte of the byte count
225    */
226   public final byte getByteCountLower() {
227     return (byte) (byteCount & 0xFF);
228   }
229 
230   /**
231    * @return the descriptor
232    */
233   public final byte getDescriptor() {
234     return (byte) (descriptor & 0xFF);
235   }
236 
237   /**
238    * @param descriptor the descriptor to set
239    */
240   public final void setDescriptor(final int descriptor) {
241     this.descriptor = descriptor & 0xFF;
242     isEOF = (this.descriptor & EOF) != 0;
243     isEOR = (this.descriptor & EOR) != 0;
244     isERROR = (this.descriptor & ERROR) != 0;
245     isRESTART = (this.descriptor & RESTART) != 0;
246   }
247 
248   /**
249    * @return the isEOF
250    */
251   public final boolean isEOF() {
252     return isEOF;
253   }
254 
255   /**
256    * @param isEOF the isEOF to set
257    */
258   public final void setEOF(final boolean isEOF) {
259     this.isEOF = isEOF;
260     descriptor |= EOF;
261   }
262 
263   /**
264    * @return the isEOR
265    */
266   public final boolean isEOR() {
267     return isEOR;
268   }
269 
270   /**
271    * @param isEOR the isEOR to set
272    */
273   public final void setEOR(final boolean isEOR) {
274     this.isEOR = isEOR;
275     descriptor |= EOR;
276   }
277 
278   /**
279    * @return the isERROR
280    */
281   public final boolean isERROR() {
282     return isERROR;
283   }
284 
285   /**
286    * @param isERROR the isERROR to set
287    */
288   public final void setERROR(final boolean isERROR) {
289     this.isERROR = isERROR;
290     descriptor |= ERROR;
291   }
292 
293   /**
294    * @return the isRESTART
295    */
296   public final boolean isRESTART() {
297     return isRESTART;
298   }
299 
300   /**
301    * @param isRESTART the isRESTART to set
302    */
303   public final void setRESTART(final boolean isRESTART) {
304     this.isRESTART = isRESTART;
305     descriptor |= RESTART;
306   }
307 
308   /**
309    * @return the markers
310    */
311   public final int[] getMarkers() {
312     return markers;
313   }
314 
315   /**
316    * @return the 6 bytes representation of the markers
317    */
318   public final byte[] getByteMarkers() {
319     final byte[] bmarkers = new byte[6];
320     if (markers == null) {
321       for (int i = 0; i < 6; i++) {
322         bmarkers[i] = 0;
323       }
324     } else {
325       for (int i = 0; i < 6; i++) {
326         bmarkers[i] = (byte) (markers[i] & 0xFF);
327       }
328     }
329     return bmarkers;
330   }
331 
332   /**
333    * Set the markers and the byte count
334    *
335    * @param markers the markers to set
336    */
337   public final void setMarkers(final int[] markers) {
338     this.markers = markers;
339     byteCount = 6;
340   }
341 
342   /**
343    * Clear the object
344    */
345   public final void clear() {
346     if (blockBuf != null) {
347       WaarpNettyUtil.release(blockBuf);
348       blockBuf = null;
349     }
350     block = null;
351     byteCount = -1;
352     descriptor = 0;
353     isEOF = false;
354     isEOR = false;
355     isERROR = false;
356     isRESTART = false;
357     markers = null;
358   }
359 
360   /**
361    * Is this Block cleared
362    *
363    * @return True if this Block is cleared
364    */
365   public final boolean isCleared() {
366     return byteCount == -1;
367   }
368 
369   @Override
370   public String toString() {
371     return "DataBlock Length:" + byteCount + " isEof:" + isEOF + " isEOR:" +
372            isEOR + " isERROR:" + isERROR + " isRESTART:" + isRESTART;
373   }
374 
375   /**
376    * Translate the given array of byte into a string in binary format
377    *
378    * @param bytes
379    * @param cutted True if each Byte should be 'blank' separated or
380    *     not
381    *
382    * @return the string
383    */
384   public static String toBinaryString(final byte[] bytes,
385                                       final boolean cutted) {
386     final StringBuilder buffer = new StringBuilder();
387     boolean first = true;
388     for (final byte b : bytes) {
389       if (cutted) {
390         if (first) {
391           first = false;
392         } else {
393           buffer.append(' ');
394         }
395       }
396       String bin = Integer.toBinaryString(b & 0xFF);
397       bin = bin.substring(0, Math.min(bin.length(), 8));
398       for (int j = 0; j < 8 - bin.length(); j++) {
399         buffer.append('0');
400       }
401       buffer.append(bin);
402     }
403     return buffer.toString();
404   }
405 }