根據C++版的改編,剛剛改完,估計使用會有問題,對於uint8處理的不好
關於使用:
1 BitStream bs = new BitStream( ); 2 bs.WriteInt32( 123 ); 3 4 int a = bs.ReadInt32( );
非常簡單
BitStream.cs
1 public class BitStream
2 {
3 #if __BITSTREAM_BIG_END
4 // Set up the read/write routines to produce Big-End network streams.
5 private const int B16_1 = 0;
6 private const int B16_0 = 1;
7
8 private const int B32_3 = 0;
9 private const int B32_2 = 1;
10 private const int B32_1 = 2;
11 private const int B32_0 = 3;
12
13 private const int B64_7 = 0;
14 private const int B64_6 = 1;
15 private const int B64_5 = 2;
16 private const int B64_4 = 3;
17 private const int B64_3 = 4;
18 private const int B64_2 = 5;
19 private const int B64_1 = 6;
20 private const int B64_0 = 7;
21
22 #else
23 // Default to producing Little-End network streams.
24 private const int B16_1 = 1;
25 private const int B16_0 = 0;
26
27 private const int B32_3 = 3;
28 private const int B32_2 = 2;
29 private const int B32_1 = 1;
30 private const int B32_0 = 0;
31
32 private const int B64_7 = 7;
33 private const int B64_6 = 6;
34 private const int B64_5 = 5;
35 private const int B64_4 = 4;
36 private const int B64_3 = 3;
37 private const int B64_2 = 2;
38 private const int B64_1 = 1;
39 private const int B64_0 = 0;
40 #endif
41 public const int BITSTREAM_STACK_ALLOCATION_SIZE = 2048;
42
43 /// Default Constructor
44 public static int BITS_TO_BYTES(int x)
45 {
46 return (((x) + 7) >> 3);
47 }
48
49 public static int BYTES_TO_BITS(int x)
50 {
51 return (x << 3);
52 }
53
54 /**
55 * @brief Packets encoding and decoding facilities
56 *
57 * Helper class to encode and decode packets.
58 *
59 */
60
61 /**
62 * Default Constructor
63 */
64
65 public BitStream()
66 {
67 numberOfBitsUsed = 0;
68 //numberOfBitsAllocated = 32 * 8;
69 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE*8;
70 readOffset = 0;
71 //data = ( unsigned char* ) malloc( 32 );
72 data = stackData;
73 copyData = true;
74 }
75
76 /**
77 * Preallocate some memory for the construction of the packet
78 * @param initialBytesToAllocate the amount of byte to pre-allocate.
79 */
80
81 public BitStream(int initialBytesToAllocate)
82 {
83 numberOfBitsUsed = 0;
84 readOffset = 0;
85 if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE)
86 {
87 data = stackData;
88 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE*8;
89 }
90 else
91 {
92 data = new Byte[initialBytesToAllocate];
93 numberOfBitsAllocated = initialBytesToAllocate << 3;
94 }
95 copyData = true;
96 }
97
98 /**
99 * Initialize the BitStream object using data from the network.
100 * Set _copyData to true if you want to make an internal copy of
101 * the data you are passing. You can then Write and do all other
102 * operations Set it to false if you want to just use a pointer to
103 * the data you are passing, in order to save memory and speed.
104 * You should only then do read operations.
105 * @param _data An array of bytes.
106 * @param lengthInBytes Size of the @em _data.
107 * @param _copyData Does a copy of the input data.
108 */
109
110 public BitStream(Byte[] _data, int lengthInBytes, bool _copyData)
111 {
112 numberOfBitsUsed = lengthInBytes << 3;
113 readOffset = 0;
114 copyData = _copyData;
115 numberOfBitsAllocated = lengthInBytes << 3;
116
117 if (copyData)
118 {
119 if (lengthInBytes > 0)
120 {
121 if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE)
122 {
123 data = stackData;
124 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3;
125 }
126 else
127 {
128 data = new Byte[lengthInBytes];
129 }
130 _data.CopyTo(data, 0);
131 }
132 else
133 data = null;
134 }
135 else
136 {
137 data = _data;
138 numberOfBitsUsed = 0;
139 }
140 }
141
142 //
143 public BitStream(Byte[] _data, int lengthInBytes, int datasize)
144 {
145 numberOfBitsUsed = datasize << 3;
146 readOffset = 0;
147 numberOfBitsAllocated = lengthInBytes << 3;
148 data = _data;
149 copyData = false;
150 }
151
152 /**
153 * Destructor
154 */
155 //~BitStream(){}
156 /**
157 * Reset the bitstream for reuse
158 */
159
160 private void Reset()
161 {
162 if (numberOfBitsUsed > 0)
163 {
164 // memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed));
165 }
166 // Don't free memory here for speed efficiency
167 //free(data); // Use realloc and free so we are more efficient than delete and new for resizing
168 numberOfBitsUsed = 0;
169 //numberOfBitsAllocated=8;
170 readOffset = 0;
171 }
172
173 public void SetBuffer(Byte[] _data, int lengthInBytes, int datasize)
174 {
175 numberOfBitsUsed = datasize << 3;
176 readOffset = 0;
177 numberOfBitsAllocated = lengthInBytes << 3;
178 data = _data;
179 copyData = false;
180 }
181
182 public void ClearBuffer()
183 {
184 numberOfBitsUsed = 0;
185 readOffset = 0;
186 numberOfBitsAllocated = 0;
187 data = null;
188 }
189
190 /**
191 * Write the native types to the end of the buffer
192 * without any compression mecanism.
193 * @param input The data
194 */
195
196 public void WriteBool(bool input)
197 {
198 if (input)
199 WriteInt8(1);
200 else
201 WriteInt8(0);
202 }
203
204 /**
205 * Write the native types to the end of the buffer
206 * without any compression mecanism.
207 * @param input The data
208 */
209
210 public void WriteUInt8(Byte input)
211 {
212 WriteBits(BitConverter.GetBytes(input), sizeof (Byte)*8, true);
213 }
214
215 //
216
217 /**
218 * Write the native types to the end of the buffer
219 * without any compression mecanism.
220 * @param input The data
221 */
222
223 public void WriteInt8(SByte input)
224 {
225 WriteBits(BitConverter.GetBytes(input), sizeof (SByte)*8, true);
226 }
227
228 /**
229 * Write the native types to the end of the buffer
230 * without any compression mecanism.
231 * @param input The data
232 */
233
234 public void WriteUInt16(UInt16 input)
235 {
236 var uint16w = new Byte[2];
237 uint16w[B16_1] = (Byte) ((Byte) (input >> 8) & (0xff));
238 uint16w[B16_0] = (Byte) (input & (0xff));
239
240 WriteBits(uint16w, sizeof (UInt16)*8, true);
241 }
242
243 /**
244 * Write the native types to the end of the buffer
245 * without any compression mecanism.
246 * @param input The data
247 */
248
249 public void WriteInt16(Int16 input)
250 {
251 var int16w = new Byte[2];
252 int16w[B16_1] = (Byte) ((Byte) (input >> 8) & (0xff));
253 int16w[B16_0] = (Byte) (input & (0xff));
254
255 WriteBits(int16w, sizeof (Int16)*8, true);
256 }
257
258 /**
259 * Write the native types to the end of the buffer
260 * without any compression mecanism.
261 * @param input The data
262 */
263
264 public void WriteUInt32(UInt32 input)
265 {
266 var uint32w = new Byte[4];
267 uint32w[B32_3] = (Byte) ((Byte) (input >> 24) & (0x000000ff));
268 uint32w[B32_2] = (Byte) ((Byte) (input >> 16) & (0x000000ff));
269 uint32w[B32_1] = (Byte) ((Byte) (input >> 8) & (0x000000ff));
270 uint32w[B32_0] = (Byte) ((input) & (0x000000ff));
271
272 WriteBits(uint32w, sizeof (UInt32)*8, true);
273 }
274
275 /**
276 * Write the native types to the end of the buffer
277 * without any compression mecanism.
278 * @param input The data
279 */
280
281 public void WriteInt32(int input)
282 {
283 var int32w = new Byte[4];
284 int32w[B32_3] = (Byte) ((Byte) (input >> 24) & (0x000000ff));
285 int32w[B32_2] = (Byte) ((Byte) (input >> 16) & (0x000000ff));
286 int32w[B32_1] = (Byte) ((Byte) (input >> 8) & (0x000000ff));
287 int32w[B32_0] = (Byte) ((input) & (0x000000ff));
288
289 WriteBits(int32w, sizeof (int)*8, true);
290 }
291
292 //#if HAS_INT64
293 /**
294 * Write the native types to the end of the buffer
295 * without any compression mecanism.
296 * @param input The data
297 */
298
299 public void WriteUInt64(UInt64 input)
300 {
301 var uint64w = new Byte[8];
302 uint64w[B64_7] = (Byte) ((input >> 56) & 0xff);
303 uint64w[B64_6] = (Byte) ((input >> 48) & 0xff);
304 uint64w[B64_5] = (Byte) ((input >> 40) & 0xff);
305 uint64w[B64_4] = (Byte) ((input >> 32) & 0xff);
306 uint64w[B64_3] = (Byte) ((input >> 24) & 0xff);
307 uint64w[B64_2] = (Byte) ((input >> 16) & 0xff);
308 uint64w[B64_1] = (Byte) ((input >> 8) & 0xff);
309 uint64w[B64_0] = (Byte) (input & 0xff);
310
311 WriteBits(uint64w, sizeof (UInt64)*8, true);
312 }
313
314 /**
315 * Write the native types to the end of the buffer
316 * without any compression mecanism.
317 * @param input The data
318 */
319
320 public void WriteInt64(Int64 input)
321 {
322 var int64w = new Byte[8];
323 int64w[B64_7] = (Byte) ((input >> 56) & 0xff);
324 int64w[B64_6] = (Byte) ((input >> 48) & 0xff);
325 int64w[B64_5] = (Byte) ((input >> 40) & 0xff);
326 int64w[B64_4] = (Byte) ((input >> 32) & 0xff);
327 int64w[B64_3] = (Byte) ((input >> 24) & 0xff);
328 int64w[B64_2] = (Byte) ((input >> 16) & 0xff);
329 int64w[B64_1] = (Byte) ((input >> 8) & 0xff);
330 int64w[B64_0] = (Byte) (input & 0xff);
331
332 WriteBits(int64w, sizeof (Int64)*8, true);
333 }
334
335 //#endif
336
337 /**
338 * Write the native types to the end of the buffer
339 * without any compression mecanism.
340 * @param input The data
341 */
342
343 public void WriteFloat(float input)
344 {
345 WriteBits(BitConverter.GetBytes(input), sizeof (float)*8, true);
346 }
347
348 /**
349 * Write the native types to the end of the buffer
350 * without any compression mechanism.
351 * @param input The data
352 */
353
354 public void WriteDouble(double input)
355 {
356 WriteBits(BitConverter.GetBytes(input), sizeof (double)*8, true);
357 }
358
359 /**
360 * Write an array or casted stream. It is supposed to
361 * be raw data. It is also not possible to deal with endian problem
362 * @param input a byte buffer
363 * @param numberOfBytes the size of the byte buffer
364 */
365
366 public void WriteBytes(Byte[] input, int numberOfBytes)
367 {
368 WriteBits(input, numberOfBytes*8, true);
369 }
370
371 /**
372 * write multi bytes string
373 * @param input
374 */
375
376 public void WriteStr(string input)
377 {
378 var len = (short) input.Length;
379 WriteUInt16((ushort) len);
380 if (len > 0)
381 {
382 WriteBytes(Encoding.Default.GetBytes(input), len);
383 }
384 }
385
386 /// **
387 // * write standard string
388 // * @param input
389 // */
390 // public void WriteStr(
391 // const std::
392 // string
393 //&
394 // input
395 //){}
396 /**
397 * Copy from another bitstream
398 * @bitStream the bitstream to copy from
399 */
400 public void WriteBS(BitStream bitStream)
401 {
402 WriteBits(bitStream.GetData(), bitStream.GetWriteOffset(), false);
403 }
404
405 /**
406 * Write the native types with simple compression.
407 * Best used with negatives and positives close to 0
408 * @param input The data.
409 */
410
411 public void WriteCompUInt8(Byte input)
412 {
413 WriteCompressed(BitConverter.GetBytes(input), sizeof (Byte)*8, true);
414 }
415
416 /**
417 * Write the native types with simple compression.
418 * Best used with negatives and positives close to 0
419 * @param input The data.
420 */
421
422 public void WriteCompInt8(SByte input)
423 {
424 WriteCompressed(BitConverter.GetBytes(input), sizeof (SByte)*8, false);
425 }
426
427 /**
428 * Write the native types with simple compression.
429 * Best used with negatives and positives close to 0
430 * @param input The data.
431 */
432
433 public void WriteCompUInt16(UInt16 input)
434 {
435 var uint16wc = new Byte[2];
436 uint16wc[B16_1] = (byte) ((Byte) (input >> 8) & (0xff));
437 uint16wc[B16_0] = (byte) (input & (0xff));
438
439 WriteCompressed(uint16wc, sizeof (UInt16)*8, true);
440 }
441
442 /**
443 * Write the native types with simple compression.
444 * Best used with negatives and positives close to 0
445 * @param input The data.
446 */
447
448 public void WriteCompInt16(Int16 input)
449 {
450 var int16wc = new Byte[2];
451 int16wc[B16_1] = (Byte) ((input >> 8) & (0xff));
452 int16wc[B16_0] = (Byte) (input & (0xff));
453
454 WriteCompressed(int16wc, sizeof (Int16)*8, false);
455 }
456
457 /**
458 * Write the native types with simple compression.
459 * Best used with negatives and positives close to 0
460 * @param input The data.
461 */
462
463 public void WriteCompUInt32(UInt32 input)
464 {
465 var uint32wc = new Byte[4];
466 uint32wc[B32_3] = (Byte) ((input >> 24) & (0x000000ff));
467 uint32wc[B32_2] = (Byte) ((input >> 16) & (0x000000ff));
468 uint32wc[B32_1] = (Byte) ((input >> 8) & (0x000000ff));
469 uint32wc[B32_0] = (Byte) ((input) & (0x000000ff));
470
471 WriteCompressed(uint32wc, sizeof (UInt32)*8, true);
472 }
473
474 /**
475 * Write the native types with simple compression.
476 * Best used with negatives and positives close to 0
477 * @param input The data.
478 */
479
480 public void WriteCompInt32(int input)
481 {
482 var int32wc = new Byte[4];
483 int32wc[B32_3] = (Byte) ((input >> 24) & (0x000000ff));
484 int32wc[B32_2] = (Byte) ((input >> 16) & (0x000000ff));
485 int32wc[B32_1] = (Byte) ((input >> 8) & (0x000000ff));
486 int32wc[B32_0] = (Byte) ((input) & (0x000000ff));
487
488 WriteCompressed(int32wc, sizeof (int)*8, false);
489 }
490
491 //#ifdef HAS_INT64
492 /**
493 * Write the native types with simple compression.
494 * Best used with negatives and positives close to 0
495 * @param input The data.
496 */
497
498 public void WriteCompUInt64(UInt64 input)
499 {
500 var uint64wc = new Byte[8];
501 uint64wc[B64_7] = (Byte) ((input >> 56) & 0xff);
502 uint64wc[B64_6] = (Byte) ((input >> 48) & 0xff);
503 uint64wc[B64_5] = (Byte) ((input >> 40) & 0xff);
504 uint64wc[B64_4] = (Byte) ((input >> 32) & 0xff);
505 uint64wc[B64_3] = (Byte) ((input >> 24) & 0xff);
506 uint64wc[B64_2] = (Byte) ((input >> 16) & 0xff);
507 uint64wc[B64_1] = (Byte) ((input >> 8) & 0xff);
508 uint64wc[B64_0] = (Byte) (input & 0xff);
509
510 WriteCompressed(uint64wc, sizeof (UInt64)*8, true);
511 }
512
513 /**
514 * Write the native types with simple compression.
515 * Best used with negatives and positives close to 0
516 * @param input The data.
517 */
518
519 public void WriteCompInt64(Int64 input)
520 {
521 var int64wc = new Byte[8];
522 int64wc[B64_7] = (Byte) ((input >> 56) & 0xff);
523 int64wc[B64_6] = (Byte) ((input >> 48) & 0xff);
524 int64wc[B64_5] = (Byte) ((input >> 40) & 0xff);
525 int64wc[B64_4] = (Byte) ((input >> 32) & 0xff);
526 int64wc[B64_3] = (Byte) ((input >> 24) & 0xff);
527 int64wc[B64_2] = (Byte) ((input >> 16) & 0xff);
528 int64wc[B64_1] = (Byte) ((input >> 8) & 0xff);
529 int64wc[B64_0] = (Byte) (input & 0xff);
530
531 WriteCompressed(int64wc, sizeof (Int64)*8, false);
532 }
533
534 //#endif
535 /**
536 * Write the native types with simple compression.
537 * Best used with negatives and positives close to 0
538 * @param input The data.
539 */
540
541 public void WriteCompFloat(float input)
542 {
543 WriteFloat(input);
544 }
545
546 /**
547 * Write the native types with simple compression.
548 * Best used with negatives and positives close to 0
549 * @param input The data.
550 */
551
552 public void WriteCompDouble(double input)
553 {
554 WriteDouble(input);
555 }
556
557 /**
558 * Read the native types from the front of the buffer
559 * @param output The readed value.
560 * @return true on success false otherwise. The result of a reading
561 * can only be wrong in the case we reach the end of the BitStream
562 * with some missing bits.
563 */
564
565 public bool ReadBool()
566 {
567 if (readOffset + 1 > numberOfBitsUsed)
568 return false;
569
570 //if (ReadBit()) // Check that bit
571 if ((data[readOffset >> 3] & (0x80 >> (readOffset++%8))) != 0) // Is it faster to just write it out here?
572 return true;
573
574 return false;
575 }
576
577 /**
578 * Read the native types from the front of the buffer
579 * @param output The readed value.
580 * @return true on success false otherwise. The result of a reading
581 * can only be wrong in the case we reach the end of the BitStream
582 * with some missing bits.
583 */
584
585 public SByte ReadUInt8()
586 {
587 var x = new Byte[sizeof (SByte)];
588 if (ReadBits(ref x, sizeof (SByte)*8))
589 {
590 return (SByte) BitConverter.ToChar(x, 0);
591 }
592 return 0;
593 }
594
595 /**
596 * Read the native types from the front of the buffer
597 * @param output The readed value.
598 * @return true on success false otherwise. The result of a reading
599 * can only be wrong in the case we reach the end of the BitStream
600 * with some missing bits.
601 */
602
603 public Byte ReadInt8()
604 {
605 var x = new Byte[sizeof (Byte)];
606 if (ReadBits(ref x, sizeof (Byte)*8))
607 {
608 return (Byte) BitConverter.ToChar(x, 0);
609 ;
610 }
611 return 0;
612 }
613
614 /**
615 * Read the native types from the front of the buffer
616 * @param output The readed value.
617 * @return true on success false otherwise. The result of a reading
618 * can only be wrong in the case we reach the end of the BitStream
619 * with some missing bits.
620 */
621
622 public UInt16 ReadUInt16()
623 {
624 var uint16r = new Byte[2];
625 if (ReadBits(ref uint16r, sizeof (UInt16)*8) != true)
626 return 0;
627 return (ushort) ((uint16r[B16_1] << 8) | uint16r[B16_0]);
628 }
629
630 /**
631 * Read the native types from the front of the buffer
632 * @param output The readed value.
633 * @return true on success false otherwise. The result of a reading
634 * can only be wrong in the case we reach the end of the BitStream
635 * with some missing bits.
636 */
637
638 public short ReadInt16()
639 {
640 var int16r = new Byte[2];
641 if (ReadBits(ref int16r, sizeof (short)*8) != true)
642 return 0;
643
644 return (short) ((int16r[B16_1] << 8) | int16r[B16_0]);
645 }
646
647 /**
648 * Read the native types from the front of the buffer
649 * @param output The readed value.
650 * @return true on success false otherwise. The result of a reading
651 * can only be wrong in the case we reach the end of the BitStream
652 * with some missing bits.
653 */
654
655 public UInt32 ReadUInt32()
656 {
657 var uint32r = new Byte[4];
658 if (ReadBits(ref uint32r, sizeof (UInt32)*8) != true)
659 return 0;
660 return (((UInt32) uint32r[B32_3]) << 24) |
661 (((UInt32) uint32r[B32_2]) << 16) |
662 (((UInt32) uint32r[B32_1]) << 8) |
663 uint32r[B32_0];
664 }
665
666 /**
667 * Read the native types from the front of the buffer
668 * @param output The readed value.
669 * @return true on success false otherwise. The result of a reading
670 * can only be wrong in the case we reach the end of the BitStream
671 * with some missing bits.
672 */
673
674 public int ReadInt32()
675 {
676 var int32r = new Byte[4];
677 if (ReadBits(ref int32r, sizeof (int)*8) != true)
678 return 0;
679 return (int32r[B32_3] << 24) |
680 (int32r[B32_2] << 16) |
681 (int32r[B32_1] << 8) |
682 int32r[B32_0];
683 }
684
685
686 //#ifdef HAS_INT64
687 /**
688 * Read the native types from the front of the buffer
689 * @param output The readed value.
690 * @return true on success false otherwise. The result of a reading
691 * can only be wrong in the case we reach the end of the BitStream
692 * with some missing bits.
693 */
694
695 public UInt64 ReadUInt64()
696 {
697 var uint64r = new Byte[8];
698 if (ReadBits(ref uint64r, sizeof (UInt64)*8) != true)
699 return 0;
700 return (((UInt64) uint64r[B64_7]) << 56) | (((UInt64) uint64r[B64_6]) << 48) |
701 (((UInt64) uint64r[B64_5]) << 40) | (((UInt64) uint64r[B64_4]) << 32) |
702 (((UInt64) uint64r[B64_3]) << 24) | (((UInt64) uint64r[B64_2]) << 16) |
703 (((UInt64) uint64r[B64_1]) << 8) | uint64r[B64_0];
704 }
705
706 /**
707 * Read the native types from the front of the buffer
708 * @param output The readed value.
709 * @return true on success false otherwise. The result of a reading
710 * can only be wrong in the case we reach the end of the BitStream
711 * with some missing bits.
712 */
713
714 public Int64 ReadInt64()
715 {
716 var int64r = new Byte[8];
717 if (ReadBits(ref int64r, sizeof (Int64)*8) != true)
718 return 0;
719 return (Int64) ((((UInt64) int64r[B64_7]) << 56) | (((UInt64) int64r[B64_6]) << 48) |
720 (((UInt64) int64r[B64_5]) << 40) | (((UInt64) int64r[B64_4]) << 32) |
721 (((UInt64) int64r[B64_3]) << 24) | (((UInt64) int64r[B64_2]) << 16) |
722 (((UInt64) int64r[B64_1]) << 8) | int64r[B64_0]);
723 }
724
725 //#endif
726 /**
727 * Read the native types from the front of the buffer
728 * @param output The readed value.
729 * @return true on success false otherwise. The result of a reading
730 * can only be wrong in the case we reach the end of the BitStream
731 * with some missing bits.
732 */
733
734 public float ReadFloat()
735 {
736 uint val = ReadUInt32();
737 return BitConverter.ToSingle(BitConverter.GetBytes(val), 0);
738 }
739
740 /**
741 * Read the native types from the front of the buffer
742 * @param output The readed value.
743 * @return true on success false otherwise. The result of a reading
744 * can only be wrong in the case we reach the end of the BitStream
745 * with some missing bits.
746 */
747
748 public double ReadDouble()
749 {
750 UInt64 val = ReadUInt64();
751 return BitConverter.ToDouble(BitConverter.GetBytes(val), 0);
752 }
753
754 /**
755 * Read an array or casted stream of byte. The array
756 * is raw data. There is no automatic conversion on
757 * big endian arch
758 * @param output The result byte array. It should be larger than @em numberOfBytes.
759 * @param numberOfBytes The number of byte to read
760 * @return true on success false if there is some missing bytes.
761 */
762
763 public bool ReadBytes(ref Byte[] output, int numberOfBytes)
764 {
765 return ReadBits(ref output, numberOfBytes*8);
766 }
767
768 /**
769 * Read standard string
770 * @return
771 */
772
773 public string ReadStr()
774 {
775 string strs;
776 ushort len = ReadUInt16();
777 if (len > 0)
778 {
779 var str = new Byte[len + 1];
780 if (ReadBytes(ref str, len))
781 {
782 str[len] = 10;
783 strs = Encoding.Default.GetString(str);
784 return strs;
785 }
786 }
787 return string.Empty;
788 }
789
790 /**
791 * Read the types you wrote with WriteCompressed
792 * @param output The read value
793 * @return true on success, false on not enough data to read
794 */
795
796 public SByte ReadCompUInt8()
797 {
798 var uint8rc = new Byte[sizeof (Byte)];
799
800 if (ReadCompressed(ref uint8rc, sizeof (Byte)*8, true))
801 {
802 return (SByte) uint8rc[0];
803 }
804 return 0;
805 }
806
807 /**
808 * Read the types you wrote with WriteCompressed
809 * @param output The read value
810 * @return true on success, false on not enough data to read
811 */
812
813 public Byte ReadCompInt8()
814 {
815 var uint8rc = new Byte[sizeof (Byte)];
816
817 if (ReadCompressed(ref uint8rc, sizeof (Byte)*8, true))
818 {
819 return uint8rc[0];
820 }
821 return 0;
822 }
823
824 /**
825 * Read the types you wrote with WriteCompressed
826 * @param output The read value
827 * @return true on success, false on not enough data to read
828 */
829
830 public UInt16 ReadCompUInt16()
831 {
832 var uint16rc = new Byte[2];
833 if (ReadCompressed(ref uint16rc, sizeof (UInt16)*8, true) != true)
834 return 0;
835 return (ushort) ((uint16rc[B16_1] << 8) |
836 uint16rc[B16_0]);
837 }
838
839 /**
840 * Read the types you wrote with WriteCompressed
841 * @param output The read value
842 * @return true on success, false on not enough data to read
843 */
844
845 public short ReadCompInt16()
846 {
847 var int16rc = new byte[2];
848 if (ReadCompressed(ref int16rc, sizeof (short)*8, false) != true) return 0;
849 return (short) ((int16rc[B16_1] << 8) | int16rc[B16_0]);
850 }
851
852 /**
853 * Read the types you wrote with WriteCompressed
854 * @param output The read value
855 * @return true on success, false on not enough data to read
856 */
857
858 public UInt32 ReadCompUInt32()
859 {
860 var uint32rc = new Byte[4];
861 if (ReadCompressed(ref uint32rc, sizeof (UInt32)*8, true) != true)
862 return 0;
863 return (((UInt32) uint32rc[B32_3]) << 24) |
864 (((UInt32) uint32rc[B32_2]) << 16) |
865 (((UInt32) uint32rc[B32_1]) << 8) |
866 uint32rc[B32_0];
867 }
868
869 /**
870 * Read the types you wrote with WriteCompressed
871 * @param output The read value
872 * @return true on success, false on not enough data to read
873 */
874
875 public int ReadCompInt32()
876 {
877 var int32rc = new Byte[4];
878 if (ReadCompressed(ref int32rc, sizeof (int)*8, false) != true)
879 return 0;
880 return (int) ((((UInt32) int32rc[B32_3]) << 24) |
881 (((UInt32) int32rc[B32_2]) << 16) |
882 (((UInt32) int32rc[B32_1]) << 8) |
883 int32rc[B32_0]);
884 }
885
886 //#ifdef HAS_INT64
887 /**
888 * Read the types you wrote with WriteCompressed
889 * @param output The read value
890 * @return true on success, false on not enough data to read
891 */
892
893 public UInt64 ReadCompUInt64()
894 {
895 var uint64rc = new Byte[8];
896 if (ReadCompressed(ref uint64rc, sizeof (UInt64)*8, true) != true)
897 return 0;
898 return (((UInt64) uint64rc[B64_7]) << 56) | (((UInt64) uint64rc[B64_6]) << 48) |
899 (((UInt64) uint64rc[B64_5]) << 40) | (((UInt64) uint64rc[B64_4]) << 32) |
900 (((UInt64) uint64rc[B64_3]) << 24) | (((UInt64) uint64rc[B64_2]) << 16) |
901 (((UInt64) uint64rc[B64_1]) << 8) | uint64rc[B64_0];
902 }
903
904 /**
905 * Read the types you wrote with WriteCompressed
906 * @param output The read value
907 * @return true on success, false on not enough data to read
908 */
909
910 public Int64 ReadCompInt64()
911 {
912 var int64rc = new Byte[8];
913 if (ReadCompressed(ref int64rc, sizeof (Int64)*8, false) != true)
914 return 0;
915 return (Int64) ((((UInt64) int64rc[B64_7]) << 56) | (((UInt64) int64rc[B64_6]) << 48) |
916 (((UInt64) int64rc[B64_5]) << 40) | (((UInt64) int64rc[B64_4]) << 32) |
917 (((UInt64) int64rc[B64_3]) << 24) | (((UInt64) int64rc[B64_2]) << 16) |
918 (((UInt64) int64rc[B64_1]) << 8) | int64rc[B64_0]);
919 }
920
921 //#endif
922 /**
923 * Read the types you wrote with WriteCompressed
924 * @param output The read value
925 * @return true on success, false on not enough data to read
926 */
927
928 public float ReadCompFloat()
929 {
930 return ReadFloat();
931 }
932
933 /**
934 * Read the types you wrote with WriteCompressed
935 * @param output The read value
936 * @return true on success, false on not enough data to read
937 */
938
939 public double ReadCompDouble()
940 {
941 return ReadDouble();
942 }
943
944 /**
945 * Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12 bytes. Will further compress y or z axis aligned vectors.
946 * Accurate to 1/32767.5.
947 * @param x x
948 * @param y y
949 * @param z z
950 */
951
952
953 /**
954 * This is good to call when you are done with the stream to make
955 * sure you didn't leave any data left over void
956 */
957
958 public void AssertStreamEmpty()
959 {
960 if (readOffset == numberOfBitsUsed)
961 throw new Exception();
962 }
963
964 // * print to the standard output the state of the stream bit by bit
965 // */
966
967 //public void PrintBits()
968 //{
969
970 //}
971 /// **
972 /// **
973 // * Ignore data we don't intend to read
974 // * @param numberOfBits The number of bits to ignore
975 // */
976 public void IgnoreBits(int numberOfBits)
977 {
978 readOffset += numberOfBits;
979 }
980
981 /**
982 * Move the write pointer to a position on the array.
983 * @param offset the offset from the start of the array.
984 * @attention
985 * Dangerous if you don't know what you are doing!
986 *
987 */
988
989 public void SetWriteOffset(int offset)
990 {
991 numberOfBitsUsed = offset;
992 }
993
994 /**
995 * Returns the length in bits of the stream
996 */
997
998 public int GetWriteOffset()
999 {
1000 return numberOfBitsUsed;
1001 }
1002
1003 /**
1004 * Returns the length in bytes of the stream
1005 */
1006
1007 public int GetNumberOfBytesUsed()
1008 {
1009 return BITS_TO_BYTES(numberOfBitsUsed);
1010 }
1011
1012 public int GetNumberOfBytesRead()
1013 {
1014 return BITS_TO_BYTES(readOffset);
1015 }
1016
1017 /**
1018 * Move the read pointer to a position on the array.
1019 * @param offset
1020 */
1021
1022 public void SetReadOffset(int offset)
1023 {
1024 readOffset = offset;
1025 }
1026
1027 public void SetByteReadOffSet(int offset)
1028 {
1029 readOffset = BYTES_TO_BITS(offset);
1030 }
1031
1032 /**
1033 * Returns the number of bits into the stream that we have read
1034 */
1035
1036 public int GetReadOffset()
1037 {
1038 return readOffset;
1039 }
1040
1041
1042 /**
1043 * Returns the number of bits left in the stream that haven't been read
1044 */
1045
1046 public int GetNumberOfUnreadBits()
1047 {
1048 return numberOfBitsUsed - readOffset;
1049 }
1050
1051 /**
1052 * Makes a copy of the internal data for you Data will point to
1053 * the stream. Returns the length in bits of the stream. Partial
1054 * bytes are left aligned
1055 * @param _data the resulting byte copy of the internal state.
1056 */
1057
1058 public int CopyData(Byte[] _data)
1059 {
1060 _data = new Byte[BITS_TO_BYTES(numberOfBitsUsed)];
1061 data.CopyTo(_data, 0);
1062 return numberOfBitsUsed;
1063 }
1064
1065 /**
1066 * Set the stream to some initial data. For internal use
1067 * Partial bytes are left aligned
1068 * @param input The data
1069 * @param numberOfBits the number of bits set in the data buffer
1070 */
1071
1072 public void SetData(Byte[] input, int numberOfBits)
1073 {
1074 if (numberOfBits <= 0)
1075 return;
1076 AddBitsAndReallocate(numberOfBits);
1077 input.CopyTo(data, 0);
1078 numberOfBitsUsed = numberOfBits;
1079 }
1080
1081 /**
1082 * Exposes the internal data.
1083 * Partial bytes are left aligned.
1084 * @return A pointer to the internal state
1085 */
1086
1087 public Byte[] GetData()
1088 {
1089 return data;
1090 }
1091
1092 /**
1093 * Write numberToWrite bits from the input source Right aligned
1094 * data means in the case of a partial byte, the bits are aligned
1095 * from the right (bit 0) rather than the left (as in the normal
1096 * internal representation) You would set this to true when
1097 * writing user data, and false when copying bitstream data, such
1098 * as writing one bitstream to another
1099 * @param input The data
1100 * @param numberOfBitsToWrite The number of bits to write
1101 * @param rightAlignedBits if true data will be right aligned
1102 */
1103
1104 public void WriteBits(Byte[] input, int numberOfBitsToWrite, bool rightAlignedBits = true)
1105 {
1106 AddBitsAndReallocate(numberOfBitsToWrite);
1107 int offset = 0;
1108 Byte dataByte;
1109 int numberOfBitsUsedMod8;
1110
1111 numberOfBitsUsedMod8 = numberOfBitsUsed%8;
1112
1113 // Faster to put the while at the top surprisingly enough
1114 while (numberOfBitsToWrite > 0)
1115 //do
1116 {
1117 dataByte = input[offset]; //*( input + offset );
1118
1119 if (numberOfBitsToWrite < 8 && rightAlignedBits)
1120 // rightAlignedBits means in the case of a partial byte, the bits are aligned from the right (bit 0) rather than the left (as in the normal internal representation)
1121 dataByte <<= 8 - numberOfBitsToWrite;
1122 // shift left to get the bits on the left, as in our internal representation
1123
1124 // Writing to a new byte each time
1125 if (numberOfBitsUsedMod8 == 0)
1126 data[numberOfBitsUsed >> 3] = dataByte; //*( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;
1127 else
1128 {
1129 // Copy over the new data.
1130 data[numberOfBitsUsed >> 3] |= (Byte) (dataByte >> (numberOfBitsUsedMod8));
1131 //*( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half
1132
1133 if (8 - (numberOfBitsUsedMod8) < 8 && 8 - (numberOfBitsUsedMod8) < numberOfBitsToWrite)
1134 // If we didn't write it all out in the first half (8 - (numberOfBitsUsed%8) is the number we wrote in the first half)
1135 {
1136 //*( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary)
1137 data[(numberOfBitsUsed >> 3) + 1] = (Byte) (dataByte << (8 - (numberOfBitsUsedMod8)));
1138 }
1139 }
1140
1141 if (numberOfBitsToWrite >= 8)
1142 numberOfBitsUsed += 8;
1143 else
1144 numberOfBitsUsed += numberOfBitsToWrite;
1145
1146 numberOfBitsToWrite -= 8;
1147
1148 offset++;
1149 }
1150 }
1151
1152 /**
1153 * Align the bitstream to the byte boundary and then write the
1154 * specified number of bits. This is faster than WriteBits but
1155 * wastes the bits to do the alignment and requires you to call
1156 * ReadAlignedBits at the corresponding read position.
1157 * @param input The data
1158 * @param numberOfBytesToWrite The size of data.
1159 */
1160
1161 public void WriteAlignedBytes(Byte[] input, int numberOfBytesToWrite)
1162 {
1163 AlignWriteToByteBoundary();
1164 // Allocate enough memory to hold everything
1165 AddBitsAndReallocate(numberOfBytesToWrite << 3);
1166
1167 // Write the data
1168 //memcpy( data + ( numberOfBitsUsed >> 3 ), input, numberOfBytesToWrite );
1169 input.CopyTo(data, (numberOfBitsUsed >> 3));
1170 numberOfBitsUsed += numberOfBytesToWrite << 3;
1171 }
1172
1173 /**
1174 * Read bits, starting at the next aligned bits. Note that the
1175 * modulus 8 starting offset of the sequence must be the same as
1176 * was used with WriteBits. This will be a problem with packet
1177 * coalescence unless you byte align the coalesced packets.
1178 * @param output The byte array larger than @em numberOfBytesToRead
1179 * @param numberOfBytesToRead The number of byte to read from the internal state
1180 * @return true if there is enough byte.
1181 */
1182
1183 public bool ReadAlignedBytes(out Byte[] output, int numberOfBytesToRead)
1184 {
1185 if (numberOfBytesToRead <= 0)
1186 {
1187 output = null;
1188 return false;
1189 }
1190 // Byte align
1191 AlignReadToByteBoundary();
1192 if (readOffset + (numberOfBytesToRead << 3) > numberOfBitsUsed)
1193 {
1194 output = null;
1195 return false;
1196 }
1197
1198 // Write the data
1199 //memcpy( output, data + ( readOffset >> 3 ), numberOfBytesToRead );
1200 output = new byte[] {};
1201 Array.Copy(data, readOffset >> 3, output, 0, numberOfBytesToRead);
1202 readOffset += numberOfBytesToRead << 3;
1203 return true;
1204 }
1205
1206 /**
1207 * Align the next write and/or read to a byte boundary. This can
1208 * be used to 'waste' bits to byte align for efficiency reasons It
1209 * can also be used to force coalesced bitstreams to start on byte
1210 * boundaries so so WriteAlignedBits and ReadAlignedBits both
1211 * calculate the same offset when aligning.
1212 */
1213
1214 public void AlignWriteToByteBoundary()
1215 {
1216 if (numberOfBitsUsed > 0)
1217 numberOfBitsUsed += 8 - ((numberOfBitsUsed - 1)%8 + 1);
1218 }
1219
1220 /**
1221 * Align the next write and/or read to a byte boundary. This can
1222 * be used to 'waste' bits to byte align for efficiency reasons It
1223 * can also be used to force coalesced bitstreams to start on byte
1224 * boundaries so so WriteAlignedBits and ReadAlignedBits both
1225 * calculate the same offset when aligning.
1226 */
1227
1228 public void AlignReadToByteBoundary()
1229 {
1230 if (readOffset > 0)
1231 readOffset += 8 - ((readOffset - 1)%8 + 1);
1232 }
1233
1234 /**
1235 * Read numberOfBitsToRead bits to the output source
1236 * alignBitsToRight should be set to true to convert internal
1237 * bitstream data to userdata It should be false if you used
1238 * WriteBits with rightAlignedBits false
1239 * @param output The resulting bits array
1240 * @param numberOfBitsToRead The number of bits to read
1241 * @param alignsBitsToRight if true bits will be right aligned.
1242 * @return true if there is enough bits to read
1243 */
1244
1245 public bool ReadBits(ref Byte[] output, int numberOfBitsToRead, bool alignBitsToRight = true)
1246 {
1247 if (readOffset + numberOfBitsToRead > numberOfBitsUsed)
1248 {
1249 output = null;
1250 return false;
1251 }
1252
1253 int readOffsetMod8;
1254 int offset = 0;
1255 //memset( output, 0, BITS_TO_BYTES( numberOfBitsToRead ) );
1256 readOffsetMod8 = readOffset%8;
1257
1258 // do
1259 // Faster to put the while at the top surprisingly enough
1260 while (numberOfBitsToRead > 0)
1261 {
1262 //*( output + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half
1263 output[offset] |= (Byte) (data[readOffset >> 3] << (readOffsetMod8));
1264 if (readOffsetMod8 > 0 && numberOfBitsToRead > 8 - (readOffsetMod8))
1265 // If we have a second half, we didn't read enough bytes in the first half
1266 //*(output + offset) |= *(data + (readOffset >> 3) + 1) >> (8 - (readOffsetMod8));
1267 output[offset] |= (Byte) (data[(readOffset >> 3) + 1] >> (8 - (readOffsetMod8)));
1268 // Second half (overlaps byte boundary)
1269
1270 numberOfBitsToRead -= 8;
1271
1272 if (numberOfBitsToRead < 0)
1273 // Reading a partial byte for the last byte, shift right so the data is aligned on the right
1274 {
1275 if (alignBitsToRight)
1276 output[offset] >>= -numberOfBitsToRead;
1277 //*(output + offset) >>= -numberOfBitsToRead;
1278
1279 readOffset += 8 + numberOfBitsToRead;
1280 }
1281 else
1282 readOffset += 8;
1283
1284 offset++;
1285 }
1286 return true;
1287 }
1288
1289 /**
1290 * --- Low level functions ---
1291 * These are for when you want to deal
1292 * with bits and don't care about type checking
1293 * Write a 0
1294 */
1295
1296 public void Write0()
1297 {
1298 AddBitsAndReallocate(1);
1299
1300 // New bytes need to be zeroed
1301
1302 if ((numberOfBitsUsed%8) == 0)
1303 data[numberOfBitsUsed >> 3] = 0;
1304
1305 numberOfBitsUsed++;
1306 }
1307
1308 /**
1309 * --- Low level functions ---
1310 * These are for when you want to deal
1311 * with bits and don't care about type checking
1312 * Write a 1
1313 */
1314
1315 public void Write1()
1316 {
1317 AddBitsAndReallocate(1);
1318
1319 int numberOfBitsMod8 = numberOfBitsUsed%8;
1320
1321 if (numberOfBitsMod8 == 0)
1322 data[numberOfBitsUsed >> 3] = 0x80;
1323 else
1324 data[numberOfBitsUsed >> 3] |= (Byte) (0x80 >> (numberOfBitsMod8));
1325 //data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
1326
1327 numberOfBitsUsed++;
1328 }
1329
1330 /**
1331 * --- Low level functions ---
1332 * These are for when you want to deal
1333 * with bits and don't care about type checking
1334 * Reads 1 bit and returns true if that bit is 1 and false if it is 0
1335 */
1336
1337 public bool ReadBit()
1338 {
1339 return (data[readOffset >> 3] & (0x80 >> (readOffset++%8))) == 1;
1340 }
1341
1342 /**
1343 * If we used the constructor version with copy data off, this
1344 * makes sure it is set to on and the data pointed to is copied.
1345 */
1346
1347 public void AssertCopyData()
1348 {
1349 if (copyData == false)
1350 {
1351 copyData = true;
1352
1353 if (numberOfBitsAllocated > 0)
1354 {
1355 var newdata = new Byte[BITS_TO_BYTES(numberOfBitsAllocated)];
1356 data.CopyTo(newdata, 0);
1357 data = newdata;
1358 }
1359 else
1360 data = null;
1361 }
1362 }
1363
1364 /**
1365 * Use this if you pass a pointer copy to the constructor
1366 * (_copyData==false) and want to overallocate to prevent
1367 * reallocation
1368 */
1369
1370 public void SetNumberOfBitsAllocated(int lengthInBits)
1371 {
1372 numberOfBitsAllocated = lengthInBits;
1373 }
1374
1375
1376 /**
1377 * Assume the input source points to a native type, compress and write it.
1378 */
1379
1380 public void WriteCompressed(Byte[] input, int size, bool unsignedData)
1381 {
1382 int currentByte = (size >> 3) - 1; // PCs
1383
1384 Byte byteMatch;
1385
1386 if (unsignedData)
1387 {
1388 byteMatch = 0;
1389 }
1390
1391 else
1392 {
1393 byteMatch = 0xFF;
1394 }
1395
1396 // Write upper bytes with a single 1
1397 // From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
1398 while (currentByte > 0)
1399 {
1400 if (input[currentByte] == byteMatch)
1401 // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted
1402 {
1403 bool b = true;
1404 WriteBool(b);
1405 }
1406 else
1407 {
1408 // Write the remainder of the data after writing 0
1409 bool b = false;
1410 WriteBool(b);
1411
1412 WriteBits(input, (currentByte + 1) << 3, true);
1413 // currentByte--;
1414
1415
1416 return;
1417 }
1418
1419 currentByte--;
1420 }
1421
1422 // If the upper half of the last byte is a 0 (positive) or 16 (negative) then write a 1 and the remaining 4 bits. Otherwise write a 0 and the 8 bites.
1423 if ((unsignedData && (((input[currentByte])) & 0xF0) == 0x00) ||
1424 (unsignedData == false && (((input[currentByte])) & 0xF0) == 0xF0))
1425 {
1426 bool b = true;
1427 WriteBool(b);
1428 var bs = new byte[4];
1429 Array.Copy(input, currentByte, bs, 0, 4);
1430 WriteBits(bs, 4, true);
1431 }
1432
1433 else
1434 {
1435 bool b = false;
1436 WriteBool(b);
1437 var bs = new byte[9];
1438 Array.Copy(input, currentByte, bs, 0, 9);
1439 WriteBits(bs, 8, true);
1440 }
1441 }
1442
1443 /**
1444 * Assume the input source points to a compressed native type.
1445 * Decompress and read it.
1446 */
1447
1448 public bool ReadCompressed(ref Byte[] output, int size, bool unsignedData)
1449 {
1450 int currentByte = (size >> 3) - 1;
1451
1452
1453 Byte byteMatch, halfByteMatch;
1454
1455 if (unsignedData)
1456 {
1457 byteMatch = 0;
1458 halfByteMatch = 0;
1459 }
1460
1461 else
1462 {
1463 byteMatch = 0xFF;
1464 halfByteMatch = 0xF0;
1465 }
1466
1467 // Upper bytes are specified with a single 1 if they match byteMatch
1468 // From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
1469 while (currentByte > 0)
1470 {
1471 // If we read a 1 then the data is byteMatch.
1472
1473 bool b = ReadBool();
1474
1475 if (b) // Check that bit
1476 {
1477 output[currentByte] = byteMatch;
1478 currentByte--;
1479 }
1480 else
1481 {
1482 // Read the rest of the bytes
1483
1484 if (ReadBits(ref output, (currentByte + 1) << 3) == false)
1485 return false;
1486
1487 return true;
1488 }
1489 }
1490 return false;
1491 }
1492
1493 /**
1494 * Reallocates (if necessary) in preparation of writing
1495 * numberOfBitsToWrite
1496 */
1497
1498 public void AddBitsAndReallocate(int numberOfBitsToWrite)
1499 {
1500 if (numberOfBitsToWrite <= 0)
1501 return;
1502
1503 int newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed;
1504
1505 if (numberOfBitsToWrite + numberOfBitsUsed > 0 &&
1506 ((numberOfBitsAllocated - 1) >> 3) < ((newNumberOfBitsAllocated - 1) >> 3))
1507 // If we need to allocate 1 or more new bytes
1508 {
1509 // Less memory efficient but saves on news and deletes
1510 newNumberOfBitsAllocated = (numberOfBitsToWrite + numberOfBitsUsed)*2;
1511 // int newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated );
1512 // Use realloc and free so we are more efficient than delete and new for resizing
1513 int amountToAllocate = BITS_TO_BYTES(newNumberOfBitsAllocated);
1514 if (data == stackData)
1515 {
1516 if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)
1517 {
1518 data = new byte[amountToAllocate];
1519
1520 // need to copy the stack data over to our new memory area too
1521 stackData.CopyTo(data, 0);
1522 }
1523 }
1524 else
1525 {
1526 data = data.Concat(new Byte[amountToAllocate - data.Length]).ToArray();
1527 //data = ( unsigned char* ) realloc( data, amountToAllocate );
1528 }
1529 // memset(data+newByteOffset, 0, ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0
1530 }
1531
1532 if (newNumberOfBitsAllocated > numberOfBitsAllocated)
1533 numberOfBitsAllocated = newNumberOfBitsAllocated;
1534 }
1535
1536 /**
1537 * Number of bits currently used
1538 */
1539 private int numberOfBitsUsed;
1540 /**
1541 * Number of bits currently allocated
1542 */
1543
1544 private
1545 int numberOfBitsAllocated;
1546
1547 /**
1548 * Current readOffset
1549 */
1550
1551 private
1552 int readOffset;
1553
1554 /**
1555 * array of byte storing the data. Points to stackData or if is bigger than that then is allocated
1556 */
1557
1558 private
1559 Byte[] data;
1560
1561 /**
1562 * true if the internal buffer is copy of the data passed to the
1563 * constructor
1564 */
1565
1566 private
1567 bool copyData;
1568
1569 private Byte[] stackData = new Byte[BITSTREAM_STACK_ALLOCATION_SIZE];
1570 }
const
這是結構體指針中的一個符號,給你寫個程序解釋一下吧,例如:
#include<stdio.h>
struct STU //定義一個結構體
{
int num;
}stu;
int main()
{
struct STU *p; //定義一個結構體指針
p=stu; //p指向stu這個結構體變量
stu.num=100; //給結構體成員num附個初值
printf("%d",p->num); //輸出stu中的num的值
return;
}
看到了吧,->的作法就是在引用結構體中的變量!!
形式如:p->結構體成員(如p->num)
他的作用相當於stu.num或(*p).num
不知道這樣解釋你明不明白、、、、、不懂了call我,O(∩_∩)O~
望采納。
這是結構體指針中的一個符號,給你寫個程序解釋一下吧,例如:
#include<stdio.h>
struct STU //定義一個結構體
{
int num;
}stu;
int main()
{
struct STU *p; //定義一個結構體指針
p=stu; //p指向stu這個結構體變量
stu.num=100; //給結構體成員num附個初值
printf("%d",p->num); //輸出stu中的num的值
return;
}
看到了吧,->的作法就是在引用結構體中的變量!!
形式如:p->結構體成員(如p->num)
他的作用相當於stu.num或(*p).num
不知道這樣解釋你明不明白、、、、、不懂了call我,O(∩_∩)O~
望采納。