This file is indexed.

/usr/include/ns3.27/ns3/buffer.h is in libns3-dev 3.27+dfsg-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2005,2006,2007 INRIA
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
 */
#ifndef BUFFER_H
#define BUFFER_H

#include <stdint.h>
#include <vector>
#include <ostream>
#include "ns3/assert.h"

#define BUFFER_FREE_LIST 1

namespace ns3 {

/**
 * \ingroup packet
 *
 * \brief automatically resized byte buffer
 *
 * This represents a buffer of bytes. Its size is
 * automatically adjusted to hold any data prepended
 * or appended by the user. Its implementation is optimized
 * to ensure that the number of buffer resizes is minimized,
 * by creating new Buffers of the maximum size ever used.
 * The correct maximum size is learned at runtime during use by 
 * recording the maximum size of each packet.
 *
 * \internal
 * The implementation of the Buffer class uses a COW (Copy On Write)
 * technique to ensure that the underlying data buffer which holds
 * the data bytes is shared among a lot of Buffer instances despite
 * data being added or removed from them.
 *
 * When multiple Buffer instances hold a reference to the same 
 * underlying BufferData object, they must be able to detect when
 * the operation they want to perform should trigger a copy of the
 * BufferData. If the BufferData::m_count field is one, it means that
 * there exist only one instance of Buffer which references the 
 * BufferData instance so, it is safe to modify it. It is also
 * safe to modify the content of a BufferData if the modification
 * falls outside of the "dirty area" defined by the BufferData.
 * In every other case, the BufferData must be copied before
 * being modified.
 *
 * To understand the way the Buffer::Add and Buffer::Remove methods
 * work, you first need to understand the "virtual offsets" used to
 * keep track of the content of buffers. Each Buffer instance
 * contains real data bytes in its BufferData instance but it also
 * contains "virtual zero data" which typically is used to represent
 * application-level payload. No memory is allocated to store the
 * zero bytes of application-level payload unless the user fragments
 * a Buffer: this application-level payload is kept track of with
 * a pair of integers which describe where in the buffer content
 * the "virtual zero area" starts and ends.
 *
 * \verbatim
 * ***: unused bytes
 * xxx: bytes "added" at the front of the zero area
 * ...: bytes "added" at the back of the zero area
 * 000: virtual zero bytes
 *
 * Real byte buffer:      |********xxxxxxxxxxxx.........*****|
 *                        |--------^ m_start
 *                        |-------------------^ m_zeroAreaStart
 *                        |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart)
 * Virtual byte buffer:           |xxxxxxxxxxxx0000000000000.........|
 *                        |--------^ m_start
 *                        |--------------------^ m_zeroAreaStart
 *                        |---------------------------------^ m_zeroAreaEnd
 *                        |------------------------------------------^ m_end
 * \endverbatim
 *
 * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end
 */
class Buffer 
{
public:
  /**
   * \brief iterator in a Buffer instance
   */
  class Iterator 
  {
public:
    inline Iterator ();
    /**
     * go forward by one byte
     */
    inline void Next (void);
    /**
     * go backward by one byte
     */
    inline void Prev (void);
    /**
     * \param delta number of bytes to go forward
     */
    inline void Next (uint32_t delta);
    /**
     * \param delta number of bytes to go backward
     */
    inline void Prev (uint32_t delta);
    /**
     * \param o the second iterator
     * \return number of bytes included between the two iterators
     *
     * This method works only if the two iterators point
     * to the same underlying buffer. Debug builds ensure
     * this with an assert.
     */
    uint32_t GetDistanceFrom (Iterator const &o) const;

    /**
     * \return true if this iterator points to the end of the byte array.
     *     false otherwise.
     */
    bool IsEnd (void) const;
    /**
     * \return true if this iterator points to the start of the byte array.
     *     false otherwise.
     */
    bool IsStart (void) const;

    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by one byte.
     */
    inline void WriteU8 (uint8_t  data);
    /**
     * \param data data to write in buffer
     * \param len number of times data must be written in buffer
     *
     * Write the data in buffer len times and advance the iterator position
     * by len byte.
     */
    inline void WriteU8 (uint8_t data, uint32_t len);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by two bytes. The format of the data written in the byte
     * buffer is non-portable. We only ensure that readU16 will
     * return exactly what we wrote with writeU16 if the program
     * is run on the same machine.
     */
    void WriteU16 (uint16_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by four bytes. The format of the data written in the byte
     * buffer is non-portable. We only ensure that readU32 will
     * return exactly what we wrote with writeU32 if the program
     * is run on the same machine.
     */
    void WriteU32 (uint32_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by eight bytes. The format of the data written in the byte
     * buffer is non-portable. We only ensure that readU64 will
     * return exactly what we wrote with writeU64 if the program
     * is run on the same machine.
     */
    void WriteU64 (uint64_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by two bytes. The data is written in least significant byte order and the
     * input data is expected to be in host order.
     */
    void WriteHtolsbU16 (uint16_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by four bytes. The data is written in least significant byte order and the
     * input data is expected to be in host order.
     */
    void WriteHtolsbU32 (uint32_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by eight bytes. The data is written in least significant byte order and the
     * input data is expected to be in host order.
     */
    void WriteHtolsbU64 (uint64_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by two bytes. The data is written in network order and the
     * input data is expected to be in host order.
     */
    inline void WriteHtonU16 (uint16_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by four bytes. The data is written in network order and the
     * input data is expected to be in host order.
     */
    inline void WriteHtonU32 (uint32_t data);
    /**
     * \param data data to write in buffer
     *
     * Write the data in buffer and advance the iterator position
     * by eight bytes. The data is written in network order and the
     * input data is expected to be in host order.
     */
    void WriteHtonU64 (uint64_t data);
    /**
     * \param buffer a byte buffer to copy in the internal buffer.
     * \param size number of bytes to copy.
     *
     * Write the data in buffer and advance the iterator position
     * by size bytes.
     */
    void Write (uint8_t const*buffer, uint32_t size);
    /**
     * \param start the start of the data to copy
     * \param end the end of the data to copy
     *
     * Write the data delimited by start and end in internal buffer
     * and advance the iterator position by the number of bytes
     * copied.
     * The input interators _must_ not point to the same Buffer as
     * we do to avoid overlapping copies. This is enforced
     * in debug builds by asserts.
     */
    void Write (Iterator start, Iterator end);

    /**
     * \return the byte read in the buffer.
     *
     * Read data, but do not advance the Iterator read.
     */
    inline uint8_t  PeekU8 (void);

    /**
     * \return the byte read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     */
    inline uint8_t  ReadU8 (void);
    /**
     * \return the two bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in the format written by writeU16.
     */
    inline uint16_t ReadU16 (void);
    /**
     * \return the four bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in the format written by writeU32.
     */
    uint32_t ReadU32 (void);
    /**
     * \return the eight bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in the format written by writeU64.
     */
    uint64_t ReadU64 (void);
    /**
     * \return the two bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in network format and returned in host format.
     */
    inline uint16_t ReadNtohU16 (void);
    /**
     * \return the four bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in network format and returned in host format.
     */
    inline uint32_t ReadNtohU32 (void);
    /**
     * \return the eight bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in network format and returned in host format.
     */
    uint64_t ReadNtohU64 (void);
    /**
     * \return the two bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in least significant byte format and returned in host format.
     */
    uint16_t ReadLsbtohU16 (void);
    /**
     * \return the four bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in least significant byte format and returned in host format.
     */
    uint32_t ReadLsbtohU32 (void);
    /**
     * \return the eight bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in least signficant byte format and returned in host format.
     */
    uint64_t ReadLsbtohU64 (void);
    /**
     * \param buffer buffer to copy data into
     * \param size number of bytes to copy
     *
     * Copy size bytes of data from the internal buffer to the
     * input buffer and advance the Iterator by the number of
     * bytes read.
     */
    void Read (uint8_t *buffer, uint32_t size);

    /**
     * \param start start iterator of the buffer to copy data into
     * \param size  number of bytes to copy
     *
     * Copy size bytes of data from the internal buffer to the input buffer via
     * the provided iterator and advance the Iterator by the number of bytes
     * read.
     */
    inline void Read (Iterator start, uint32_t size);

    /**
     * \brief Calculate the checksum.
     * \param size size of the buffer.
     * \return checksum
     */
    uint16_t CalculateIpChecksum (uint16_t size);

    /**
     * \brief Calculate the checksum.
     * \param size size of the buffer.
     * \param initialChecksum initial value
     * \return checksum
     */
    uint16_t CalculateIpChecksum (uint16_t size, uint32_t initialChecksum);

    /**
     * \returns the size of the underlying buffer we are iterating
     */
    uint32_t GetSize (void) const;

    /**
     * \returns the size left to read of the underlying buffer we are iterating
     */
    uint32_t GetRemainingSize (void) const;

private:
    /// Friend class
    friend class Buffer;
    /**
     * Constructor - initializes the iterator to point to the buffer start
     *
     * \param buffer the buffer this iterator refers to
     */
    inline Iterator (Buffer const*buffer);
    /**
     * Constructor - initializes the iterator to point to the buffer end
     *
     * \param buffer the buffer this iterator refers to
     * \param dummy not used param
     */
    inline Iterator (Buffer const*buffer, bool dummy);
    /**
     * Initializes the iterator values
     *
     * \param buffer the buffer this iterator refers to
     */
    inline void Construct (const Buffer *buffer);
    /**
     * Checks that the [start, end) is not in the "virtual zero area".
     *
     * \param start start buffer position
     * \param end end buffer position
     * \returns true if [start, end) is not in the "virtual zero area".
     */
    bool CheckNoZero (uint32_t start, uint32_t end) const;
    /**
     * Checks that the buffer position is not in the "virtual zero area".
     *
     * \param i buffer position
     * \returns true if not in the "virtual zero area".
     */
    bool Check (uint32_t i) const;
    /**
     * \return the two bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in network format and returned in host format.
     *
     * \warning this is the slow version, please use ReadNtohU16 (void)
     */
    uint16_t SlowReadNtohU16 (void);
    /**
     * \return the four bytes read in the buffer.
     *
     * Read data and advance the Iterator by the number of bytes
     * read.
     * The data is read in network format and returned in host format.
     *
     * \warning this is the slow version, please use ReadNtohU32 (void)
     */
    uint32_t SlowReadNtohU32 (void);
    /**
     * \brief Returns an appropriate message indicating a read error
     * \returns the error message
     */
    std::string GetReadErrorMessage (void) const;
    /**
     * \brief Returns an appropriate message indicating a write error
     *
     * The message depends on the actual Buffer::Iterator status.
     *
     * \returns the error message
     */
    std::string GetWriteErrorMessage (void) const;

    /**
     * offset in virtual bytes from the start of the data buffer to the
     * start of the "virtual zero area".
     */
    uint32_t m_zeroStart;
    /**
     * offset in virtual bytes from the start of the data buffer to the
     * end of the "virtual zero area".
     */
    uint32_t m_zeroEnd;
    /**
     * offset in virtual bytes from the start of the data buffer to the
     * start of the data which can be read by this iterator
     */
    uint32_t m_dataStart;
    /**
     * offset in virtual bytes from the start of the data buffer to the
     * end of the data which can be read by this iterator
     */
    uint32_t m_dataEnd;
    /**
     * offset in virtual bytes from the start of the data buffer to the
     * current position represented by this iterator.
     */
    uint32_t m_current;
    /**
     * a pointer to the underlying byte buffer. All offsets are relative
     * to this pointer.
     */
    uint8_t *m_data;
  };

  /**
   * \return the number of bytes stored in this buffer.
   */
  inline uint32_t GetSize (void) const;

  /**
   * \return a pointer to the start of the internal 
   * byte buffer.
   *
   * The returned pointer points to an area of
   * memory which is ns3::Buffer::GetSize () bytes big.
   * Please, try to never ever use this method. It is really
   * evil and is present only for a few specific uses.
   */
  uint8_t const*PeekData (void) const;

  /**
   * \param start size to reserve
   *
   * Add bytes at the start of the Buffer. The
   * content of these bytes is undefined but debugging
   * builds initialize them to 0x33.
   * Any call to this method invalidates any Iterator
   * pointing to this Buffer.
   */
  void AddAtStart (uint32_t start);
  /**
   * \param end size to reserve
   *
   * Add bytes at the end of the Buffer. The
   * content of these bytes is undefined but debugging
   * builds initialize them to 0x33.
   * Any call to this method invalidates any Iterator
   * pointing to this Buffer.
   */
  void AddAtEnd (uint32_t end);

  /**
   * \param o the buffer to append to the end of this buffer.
   *
   * Add bytes at the end of the Buffer.
   * Any call to this method invalidates any Iterator
   * pointing to this Buffer.
   */
  void AddAtEnd (const Buffer &o);
  /**
   * \param start size to remove
   *
   * Remove bytes at the start of the Buffer.
   * Any call to this method invalidates any Iterator
   * pointing to this Buffer.
   */
  void RemoveAtStart (uint32_t start);
  /**
   * \param end size to remove
   *
   * Remove bytes at the end of the Buffer.
   * Any call to this method invalidates any Iterator
   * pointing to this Buffer.
   */
  void RemoveAtEnd (uint32_t end);

  /**
   * \param start offset from start of packet
   * \param length
   *
   * \return a fragment of size length starting at offset
   * start.
   */
  Buffer CreateFragment (uint32_t start, uint32_t length) const;

  /**
   * \return an Iterator which points to the
   * start of this Buffer.
   */
  inline Buffer::Iterator Begin (void) const;
  /**
   * \return an Iterator which points to the
   * end of this Buffer.
   */
  inline Buffer::Iterator End (void) const;

  /**
   * \brief Return the number of bytes required for serialization.
   * \return the number of bytes.
   */
  uint32_t GetSerializedSize (void) const;

  /**
   * \return zero if buffer not large enough
   * \param buffer points to serialization buffer
   * \param maxSize max number of bytes to write
   *
   * This buffer's contents are serialized into the raw 
   * character buffer parameter. Note: The zero length 
   * data is not copied entirely. Only the length of 
   * zero byte data is serialized.
   */
  uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;

  /**
   * \return zero if a complete buffer is not deserialized
   * \param buffer points to buffer for deserialization
   * \param size number of bytes to deserialize
   *
   * The raw character buffer is deserialized and all the 
   * data is placed into this buffer.
   */
  uint32_t Deserialize (const uint8_t* buffer, uint32_t size);

  /** 
   * Copy the specified amount of data from the buffer to the given output stream.
   * 
   * @param os the output stream
   * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
   */
  void CopyData (std::ostream *os, uint32_t size) const;

  /**
   * Copy the specified amount of data from the buffer to the given buffer.
   *
   * @param buffer the output buffer
   * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
   * @returns the amount of bytes copied
   */
  uint32_t CopyData (uint8_t *buffer, uint32_t size) const;

  /**
   * \brief Copy constructor
   * \param o the buffer to copy
   */
  inline Buffer (Buffer const &o);
  /**
   * \brief Assignment operator
   * \param o the buffer to copy
   * \return a reference to the buffer
   */
  Buffer &operator = (Buffer const &o);
  Buffer ();
  /**
   * \brief Constructor
   *
   * The buffer will be initialized with zeroes up to its size.
   *
   * \param dataSize the buffer size
   */
  Buffer (uint32_t dataSize);
  /**
   * \brief Constructor
   *
   * If initialize is set to true, the buffer will be initialized
   * with zeroes up to its size.
   *
   * \param dataSize the buffer size.
   * \param initialize initialize the buffer with zeroes.
   */
  Buffer (uint32_t dataSize, bool initialize);
  ~Buffer ();
private:
  /**
   * This data structure is variable-sized through its last member whose size
   * is determined at allocation time and stored in the m_size field.
   *
   * The so-called "dirty area" describes the area in the buffer which
   * has been reserved and used by a user. Multiple Buffer instances
   * may reference the same Buffer::Data object instance and may
   * reference different parts of the underlying byte buffer. The
   * "dirty area" is union of all the areas referenced by the Buffer
   * instances which reference the same BufferData instance.
   * New user data can be safely written only outside of the "dirty
   * area" if the reference count is higher than 1 (that is, if
   * more than one Buffer instance references the same BufferData).
   */
  struct Data
  {
    /**
     * The reference count of an instance of this data structure.
     * Each buffer which references an instance holds a count.
     */
    uint32_t m_count;
    /**
     * the size of the m_data field below.
     */
    uint32_t m_size;
    /**
     * offset from the start of the m_data field below to the
     * start of the area in which user bytes were written.
     */
    uint32_t m_dirtyStart;
    /**
     * offset from the start of the m_data field below to the
     * end of the area in which user bytes were written.
     */
    uint32_t m_dirtyEnd;
    /**
     * The real data buffer holds _at least_ one byte.
     * Its real size is stored in the m_size field.
     */
    uint8_t m_data[1];
  };

  /**
   * \brief Create a full copy of the buffer, including
   * all the internal structures.
   *
   * \returns a copy of the buffer
   */
  Buffer CreateFullCopy (void) const;

  /**
   * \brief Transform a "Virtual byte buffer" into a "Real byte buffer"
   */
  void TransformIntoRealBuffer (void) const;
  /**
   * \brief Checks the internal buffer structures consistency
   *
   * Used only for debugging purposes.
   *
   * \returns true if the buffer status is consistent.
   */
  bool CheckInternalState (void) const;

  /**
   * \brief Initializes the buffer with a number of zeroes.
   *
   * \param zeroSize the zeroes size
   */
  void Initialize (uint32_t zeroSize);

  /**
   * \brief Get the buffer real size.
   * \warning The real size is the actual memory used by the buffer.
   * \returns the memory used by the buffer.
   */
  uint32_t GetInternalSize (void) const;

  /**
   * \brief Get the buffer end position.
   * \returns the buffer end index.
   */
  uint32_t GetInternalEnd (void) const;

  /**
   * \brief Recycle the buffer memory
   * \param data the buffer data storage
   */
  static void Recycle (struct Buffer::Data *data);
  /**
   * \brief Create a buffer data storage
   * \param size the storage size to create
   * \returns a pointer to the created buffer storage
   */
  static struct Buffer::Data *Create (uint32_t size);
  /**
   * \brief Allocate a buffer data storage
   * \param reqSize the storage size to create
   * \returns a pointer to the allocated buffer storage
   */
  static struct Buffer::Data *Allocate (uint32_t reqSize);
  /**
   * \brief Deallocate the buffer memory
   * \param data the buffer data storage
   */
  static void Deallocate (struct Buffer::Data *data);

  struct Data *m_data; //!< the buffer data storage

  /**
   * keep track of the maximum value of m_zeroAreaStart across
   * the lifetime of a Buffer instance. This variable is used
   * purely as a source of information for the heuristics which
   * decide on the position of the zero area in new buffers.
   * It is read from the Buffer destructor to update the global
   * heuristic data and these global heuristic data are used from
   * the Buffer constructor to choose an initial value for 
   * m_zeroAreaStart.
   */
  uint32_t m_maxZeroAreaStart;
  /**
   * location in a newly-allocated buffer where you should start
   * writing data. i.e., m_start should be initialized to this 
   * value.
   */
  static uint32_t g_recommendedStart;

  /**
   * offset to the start of the virtual zero area from the start
   * of m_data->m_data
   */
  uint32_t m_zeroAreaStart;
  /**
   * offset to the end of the virtual zero area from the start
   * of m_data->m_data
   */
  uint32_t m_zeroAreaEnd;
  /**
   * offset to the start of the data referenced by this Buffer
   * instance from the start of m_data->m_data
   */
  uint32_t m_start;
  /**
   * offset to the end of the data referenced by this Buffer
   * instance from the start of m_data->m_data
   */
  uint32_t m_end;

#ifdef BUFFER_FREE_LIST
  /// Container for buffer data
  typedef std::vector<struct Buffer::Data*> FreeList;
  /// Local static destructor structure
  struct LocalStaticDestructor 
  {
    ~LocalStaticDestructor ();
  };
  static uint32_t g_maxSize; //!< Max observed data size
  static FreeList *g_freeList; //!< Buffer data container
  static struct LocalStaticDestructor g_localStaticDestructor; //!< Local static destructor
#endif
};

} // namespace ns3

#include "ns3/assert.h"
#include <cstring>

namespace ns3 {

Buffer::Iterator::Iterator ()
  : m_zeroStart (0),
    m_zeroEnd (0),
    m_dataStart (0),
    m_dataEnd (0),
    m_current (0),
    m_data (0)
{
}
Buffer::Iterator::Iterator (Buffer const*buffer)
{
  Construct (buffer);
  m_current = m_dataStart;
}
Buffer::Iterator::Iterator (Buffer const*buffer, bool dummy)
{
  Construct (buffer);
  m_current = m_dataEnd;
}

void
Buffer::Iterator::Construct (const Buffer *buffer)
{
  m_zeroStart = buffer->m_zeroAreaStart;
  m_zeroEnd = buffer->m_zeroAreaEnd;
  m_dataStart = buffer->m_start;
  m_dataEnd = buffer->m_end;
  m_data = buffer->m_data->m_data;
}

void 
Buffer::Iterator::Next (void)
{
  NS_ASSERT (m_current + 1 <= m_dataEnd);
  m_current++;
}
void 
Buffer::Iterator::Prev (void)
{
  NS_ASSERT (m_current >= 1);
  m_current--;
}
void 
Buffer::Iterator::Next (uint32_t delta)
{
  NS_ASSERT (m_current + delta <= m_dataEnd);
  m_current += delta;
}
void 
Buffer::Iterator::Prev (uint32_t delta)
{
  NS_ASSERT (m_current >= delta);
  m_current -= delta;
}
void
Buffer::Iterator::WriteU8 (uint8_t data)
{
  NS_ASSERT_MSG (Check (m_current),
                 GetWriteErrorMessage ());

  if (m_current < m_zeroStart)
    {
      m_data[m_current] = data;
      m_current++;
    }
  else
    {
      m_data[m_current - (m_zeroEnd-m_zeroStart)] = data;
      m_current++;
    }
}

void 
Buffer::Iterator::WriteU8 (uint8_t  data, uint32_t len)
{
  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + len),
                 GetWriteErrorMessage ());
  if (m_current <= m_zeroStart)
    {
      std::memset (&(m_data[m_current]), data, len);
      m_current += len;
    }
  else
    {
      uint8_t *buffer = &m_data[m_current - (m_zeroEnd-m_zeroStart)];
      std::memset (buffer, data, len);
      m_current += len;
    }
}

void 
Buffer::Iterator::WriteHtonU16 (uint16_t data)
{
  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + 2),
                 GetWriteErrorMessage ());
  uint8_t *buffer;
  if (m_current + 2 <= m_zeroStart)
    {
      buffer = &m_data[m_current];
    }
  else
    {
      buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
    }
  buffer[0] = (data >> 8)& 0xff;
  buffer[1] = (data >> 0)& 0xff;
  m_current+= 2;
}

void 
Buffer::Iterator::WriteHtonU32 (uint32_t data)
{
  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + 4),
                 GetWriteErrorMessage ());

  uint8_t *buffer;
  if (m_current + 4 <= m_zeroStart)
    {
      buffer = &m_data[m_current];
    }
  else
    {
      buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
    }
  buffer[0] = (data >> 24)& 0xff;
  buffer[1] = (data >> 16)& 0xff;
  buffer[2] = (data >> 8)& 0xff;
  buffer[3] = (data >> 0)& 0xff;
  m_current+= 4;
}

uint16_t 
Buffer::Iterator::ReadNtohU16 (void)
{
  uint8_t *buffer;
  if (m_current + 2 <= m_zeroStart)
    {
      buffer = &m_data[m_current];
    }
  else if (m_current >= m_zeroEnd)
    {
      buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
    }
  else
    {
      return SlowReadNtohU16 ();
    }
  uint16_t retval = 0;
  retval |= buffer[0];
  retval <<= 8;
  retval |= buffer[1];
  m_current += 2;
  return retval;
}

uint32_t 
Buffer::Iterator::ReadNtohU32 (void)
{
  uint8_t *buffer;
  if (m_current + 4 <= m_zeroStart)
    {
      buffer = &m_data[m_current];
    }
  else if (m_current >= m_zeroEnd)
    {
      buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
    }
  else
    {
      return SlowReadNtohU32 ();
    }
  uint32_t retval = 0;
  retval |= buffer[0];
  retval <<= 8;
  retval |= buffer[1];
  retval <<= 8;
  retval |= buffer[2];
  retval <<= 8;
  retval |= buffer[3];
  m_current += 4;
  return retval;
}

uint8_t
Buffer::Iterator::PeekU8 (void)
{
  NS_ASSERT_MSG (m_current >= m_dataStart &&
                 m_current < m_dataEnd,
                 GetReadErrorMessage ());

  if (m_current < m_zeroStart)
    {
      uint8_t data = m_data[m_current];
      return data;
    }
  else if (m_current < m_zeroEnd)
    {
      return 0;
    }
  else
    {
      uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)];
      return data;
    }
}

uint8_t
Buffer::Iterator::ReadU8 (void)
{
  uint8_t ret = PeekU8 ();
  m_current ++;
  return ret;
}

uint16_t 
Buffer::Iterator::ReadU16 (void)
{
  uint8_t byte0 = ReadU8 ();
  uint8_t byte1 = ReadU8 ();
  uint16_t data = byte1;
  data <<= 8;
  data |= byte0;

  return data;
}

void
Buffer::Iterator::Read (Buffer::Iterator start, uint32_t size)
{
  Buffer::Iterator end = *this;
  end.Next (size);
  
  start.Write (*this, end);
}


Buffer::Buffer (Buffer const&o)
  : m_data (o.m_data),
    m_maxZeroAreaStart (o.m_zeroAreaStart),
    m_zeroAreaStart (o.m_zeroAreaStart),
    m_zeroAreaEnd (o.m_zeroAreaEnd),
    m_start (o.m_start),
    m_end (o.m_end)
{
  m_data->m_count++;
  NS_ASSERT (CheckInternalState ());
}

uint32_t 
Buffer::GetSize (void) const
{
  return m_end - m_start;
}

Buffer::Iterator 
Buffer::Begin (void) const
{
  NS_ASSERT (CheckInternalState ());
  return Buffer::Iterator (this);
}
Buffer::Iterator 
Buffer::End (void) const
{
  NS_ASSERT (CheckInternalState ());
  return Buffer::Iterator (this, false);
}



} // namespace ns3

#endif /* BUFFER_H */