src/common/buffer.h
author Nicola Baldo <nbaldo@cttc.es>
Thu Aug 13 09:36:16 2009 +0200 (2009-08-13)
changeset 4708 b251fb79becb
parent 4518 31f2881aa214
child 5842 e5571955464f
permissions -rw-r--r--
bug 639: Buffer::CopyData is buggy.
mathieu@150
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@9
     2
/*
mathieu@1461
     3
 * Copyright (c) 2005,2006,2007 INRIA
mathieu@9
     4
 *
mathieu@9
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@9
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@9
     7
 * published by the Free Software Foundation;
mathieu@9
     8
 *
mathieu@9
     9
 * This program is distributed in the hope that it will be useful,
mathieu@9
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@9
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@9
    12
 * GNU General Public License for more details.
mathieu@9
    13
 *
mathieu@9
    14
 * You should have received a copy of the GNU General Public License
mathieu@9
    15
 * along with this program; if not, write to the Free Software
mathieu@9
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@9
    17
 *
mathieu@9
    18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@9
    19
 */
mathieu@9
    20
#ifndef BUFFER_H
mathieu@9
    21
#define BUFFER_H
mathieu@9
    22
mathieu@9
    23
#include <stdint.h>
mathieu@9
    24
#include <vector>
mathieu@4518
    25
#include <ostream>
mathieu@9
    26
mathieu@1492
    27
#define BUFFER_HEURISTICS 1
mathieu@1491
    28
#define BUFFER_USE_INLINE 1
mathieu@1491
    29
mathieu@1491
    30
mathieu@1488
    31
#ifdef BUFFER_USE_INLINE
mathieu@1488
    32
#define BUFFER_INLINE inline
mathieu@1488
    33
#else
mathieu@1488
    34
#define BUFFER_INLINE
mathieu@1488
    35
#endif
mathieu@1488
    36
mathieu@16
    37
namespace ns3 {
mathieu@9
    38
mathieu@9
    39
/**
tomh@3182
    40
 * \ingroup packet
tomh@3182
    41
 *
mathieu@9
    42
 * \brief automatically resized byte buffer
mathieu@9
    43
 *
mathieu@9
    44
 * This represents a buffer of bytes. Its size is
mathieu@9
    45
 * automatically adjusted to hold any data prepended
mathieu@9
    46
 * or appended by the user. Its implementation is optimized
mathieu@9
    47
 * to ensure that the number of buffer resizes is minimized,
mathieu@9
    48
 * by creating new Buffers of the maximum size ever used.
mathieu@9
    49
 * The correct maximum size is learned at runtime during use by 
mathieu@9
    50
 * recording the maximum size of each packet.
mathieu@1491
    51
 *
mathieu@1491
    52
 * \internal
mathieu@1491
    53
 * The implementation of the Buffer class uses a COW (Copy On Write)
mathieu@1491
    54
 * technique to ensure that the underlying data buffer which holds
mathieu@1491
    55
 * the data bytes is shared among a lot of Buffer instances despite
mathieu@1491
    56
 * data being added or removed from them.
mathieu@1491
    57
 *
mathieu@1491
    58
 * When multiple Buffer instances hold a reference to the same 
mathieu@1491
    59
 * underlying BufferData object, they must be able to detect when
mathieu@1491
    60
 * the operation they want to perform should trigger a copy of the
mathieu@1491
    61
 * BufferData. If the BufferData::m_count field is one, it means that
mathieu@1491
    62
 * there exist only one instance of Buffer which references the 
mathieu@1491
    63
 * BufferData instance so, it is safe to modify it. It is also
tomh@3170
    64
 * safe to modify the content of a BufferData if the modification
tomh@3170
    65
 * falls outside of the "dirty area" defined by the BufferData.
mathieu@1491
    66
 * In every other case, the BufferData must be copied before
mathieu@1491
    67
 * being modified.
mathieu@1491
    68
 *
mathieu@1491
    69
 * To understand the way the Buffer::Add and Buffer::Remove methods
mathieu@1491
    70
 * work, you first need to understand the "virtual offsets" used to
mathieu@1491
    71
 * keep track of the content of buffers. Each Buffer instance
mathieu@1491
    72
 * contains real data bytes in its BufferData instance but it also
mathieu@1491
    73
 * contains "virtual zero data" which typically is used to represent
mathieu@1491
    74
 * application-level payload. No memory is allocated to store the
mathieu@1491
    75
 * zero bytes of application-level payload unless the user fragments
mathieu@1491
    76
 * a Buffer: this application-level payload is kept track of with
mathieu@1491
    77
 * a pair of integers which describe where in the buffer content
mathieu@1491
    78
 * the "virtual zero area" starts and ends.
mathieu@1491
    79
 *
mathieu@1491
    80
 * ***: unused bytes
mathieu@1491
    81
 * xxx: bytes "added" at the front of the zero area
mathieu@1491
    82
 * ...: bytes "added" at the back of the zero area
mathieu@1491
    83
 * 000: virtual zero bytes
mathieu@1491
    84
 *
mathieu@1491
    85
 * Real byte buffer:      |********xxxxxxxxxxxx.........*****|
mathieu@1491
    86
 *                        |--------^ m_start
mathieu@1491
    87
 *                        |-------------------^ m_zeroAreaStart
mathieu@1491
    88
 *                        |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart)
mathieu@1491
    89
 * virtual byte buffer:           |xxxxxxxxxxxx0000000000000.........|
mathieu@1491
    90
 *                        |--------^ m_start
mathieu@1491
    91
 *                        |--------------------^ m_zeroAreaStart
mathieu@1491
    92
 *                        |---------------------------------^ m_zeroAreaEnd
mathieu@1491
    93
 *                        |------------------------------------------^ m_end
mathieu@1491
    94
 *
mathieu@1491
    95
 * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end
mathieu@9
    96
 */
mathieu@2792
    97
class Buffer 
mathieu@2792
    98
{
mathieu@9
    99
public:
mathieu@150
   100
  /**
mathieu@150
   101
   * \brief iterator in a Buffer instance
mathieu@150
   102
   */
mathieu@2792
   103
  class Iterator 
mathieu@2792
   104
  {
mathieu@150
   105
  public:
mathieu@1461
   106
      Iterator ();
mathieu@150
   107
      /**
mathieu@150
   108
       * go forward by one byte
mathieu@150
   109
       */
mathieu@1461
   110
      void Next (void);
mathieu@150
   111
      /**
mathieu@150
   112
       * go backward by one byte
mathieu@150
   113
       */
mathieu@1461
   114
      void Prev (void);
mathieu@150
   115
      /**
mathieu@150
   116
       * \param delta number of bytes to go forward
mathieu@150
   117
       */
mathieu@1461
   118
      void Next (uint32_t delta);
mathieu@150
   119
      /**
mathieu@150
   120
       * \param delta number of bytes to go backward
mathieu@150
   121
       */
mathieu@1461
   122
      void Prev (uint32_t delta);
mathieu@150
   123
      /**
mathieu@150
   124
       * \param o the second iterator
mathieu@150
   125
       * \return number of bytes included between the two iterators
mathieu@150
   126
       *
mathieu@150
   127
       * This method works only if the two iterators point
mathieu@150
   128
       * to the same underlying buffer. Debug builds ensure
mathieu@150
   129
       * this with an assert.
mathieu@150
   130
       */
mathieu@1461
   131
      uint32_t GetDistanceFrom (Iterator const &o) const;
mathieu@150
   132
      
mathieu@150
   133
      /**
mathieu@150
   134
       * \return true if this iterator points to the end of the byte array.
mathieu@150
   135
       *     false otherwise.
mathieu@150
   136
       */
mathieu@1461
   137
      bool IsEnd (void) const;
mathieu@150
   138
      /**
mathieu@150
   139
       * \return true if this iterator points to the start of the byte array.
mathieu@150
   140
       *     false otherwise.
mathieu@150
   141
       */
mathieu@1461
   142
      bool IsStart (void) const;
mathieu@9
   143
mathieu@150
   144
      /**
mathieu@150
   145
       * \param data data to write in buffer
mathieu@150
   146
       *
mathieu@150
   147
       * Write the data in buffer and avance the iterator position
mathieu@150
   148
       * by one byte.
mathieu@150
   149
       */
mathieu@1488
   150
      BUFFER_INLINE void WriteU8 (uint8_t  data);
mathieu@150
   151
      /**
mathieu@150
   152
       * \param data data to write in buffer
mathieu@150
   153
       * \param len number of times data must be written in buffer
mathieu@150
   154
       *
mathieu@150
   155
       * Write the data in buffer len times and avance the iterator position
mathieu@150
   156
       * by len byte.
mathieu@150
   157
       */
mathieu@1488
   158
      BUFFER_INLINE void WriteU8 (uint8_t data, uint32_t len);
mathieu@150
   159
      /**
mathieu@150
   160
       * \param data data to write in buffer
mathieu@150
   161
       *
mathieu@150
   162
       * Write the data in buffer and avance the iterator position
mathieu@150
   163
       * by two bytes. The format of the data written in the byte
mathieu@150
   164
       * buffer is non-portable. We only ensure that readU16 will
mathieu@150
   165
       * return exactly what we wrote with writeU16 if the program
mathieu@150
   166
       * is run on the same machine.
mathieu@150
   167
       */
mathieu@1461
   168
      void WriteU16 (uint16_t data);
mathieu@150
   169
      /**
mathieu@150
   170
       * \param data data to write in buffer
mathieu@150
   171
       *
mathieu@150
   172
       * Write the data in buffer and avance the iterator position
mathieu@150
   173
       * by four bytes. The format of the data written in the byte
mathieu@150
   174
       * buffer is non-portable. We only ensure that readU32 will
mathieu@150
   175
       * return exactly what we wrote with writeU32 if the program
mathieu@150
   176
       * is run on the same machine.
mathieu@150
   177
       */
mathieu@1461
   178
      void WriteU32 (uint32_t data);
mathieu@150
   179
      /**
mathieu@150
   180
       * \param data data to write in buffer
mathieu@150
   181
       *
mathieu@150
   182
       * Write the data in buffer and avance the iterator position
mathieu@150
   183
       * by eight bytes. The format of the data written in the byte
mathieu@150
   184
       * buffer is non-portable. We only ensure that readU64 will
mathieu@150
   185
       * return exactly what we wrote with writeU64 if the program
mathieu@150
   186
       * is run on the same machine.
mathieu@150
   187
       */
mathieu@1461
   188
      void WriteU64 (uint64_t data);
mathieu@150
   189
      /**
mathieu@150
   190
       * \param data data to write in buffer
mathieu@150
   191
       *
mathieu@150
   192
       * Write the data in buffer and avance the iterator position
mathieu@150
   193
       * by two bytes. The data is written in network order and the
mathieu@150
   194
       * input data is expected to be in host order.
mathieu@150
   195
       */
mathieu@2792
   196
      void WriteHtolsbU16 (uint16_t data);
mathieu@2792
   197
      /**
mathieu@2792
   198
       * \param data data to write in buffer
mathieu@2792
   199
       *
mathieu@2792
   200
       * Write the data in buffer and avance the iterator position
mathieu@2792
   201
       * by four bytes. The data is written in least significant byte order and the
mathieu@2792
   202
       * input data is expected to be in host order.
mathieu@2792
   203
       */
mathieu@2792
   204
      void WriteHtolsbU32 (uint32_t data);
mathieu@2792
   205
      /**
mathieu@2792
   206
       * \param data data to write in buffer
mathieu@2792
   207
       *
mathieu@2792
   208
       * Write the data in buffer and avance the iterator position
mathieu@2792
   209
       * by eight bytes. The data is written in least significant byte order and the
mathieu@2792
   210
       * input data is expected to be in host order.
mathieu@2792
   211
       */
mathieu@2792
   212
      void WriteHtolsbU64 (uint64_t data);
mathieu@2792
   213
      /**
mathieu@2792
   214
       * \param data data to write in buffer
mathieu@2792
   215
       *
mathieu@2792
   216
       * Write the data in buffer and avance the iterator position
mathieu@2792
   217
       * by two bytes. The data is written in least significant byte order and the
mathieu@2792
   218
       * input data is expected to be in host order.
mathieu@2792
   219
       */
mathieu@1461
   220
      void WriteHtonU16 (uint16_t data);
mathieu@150
   221
      /**
mathieu@150
   222
       * \param data data to write in buffer
mathieu@150
   223
       *
mathieu@150
   224
       * Write the data in buffer and avance the iterator position
mathieu@150
   225
       * by four bytes. The data is written in network order and the
mathieu@150
   226
       * input data is expected to be in host order.
mathieu@150
   227
       */
mathieu@1461
   228
      void WriteHtonU32 (uint32_t data);
mathieu@150
   229
      /**
mathieu@150
   230
       * \param data data to write in buffer
mathieu@150
   231
       *
mathieu@150
   232
       * Write the data in buffer and avance the iterator position
mathieu@150
   233
       * by eight bytes. The data is written in network order and the
mathieu@150
   234
       * input data is expected to be in host order.
mathieu@150
   235
       */
mathieu@1461
   236
      void WriteHtonU64 (uint64_t data);
mathieu@150
   237
      /**
mathieu@150
   238
       * \param buffer a byte buffer to copy in the internal buffer.
mathieu@150
   239
       * \param size number of bytes to copy.
mathieu@150
   240
       *
mathieu@150
   241
       * Write the data in buffer and avance the iterator position
mathieu@150
   242
       * by size bytes.
mathieu@150
   243
       */
mathieu@1461
   244
      void Write (uint8_t const*buffer, uint32_t size);
mathieu@150
   245
      /**
mathieu@150
   246
       * \param start the start of the data to copy
mathieu@150
   247
       * \param end the end of the data to copy
mathieu@150
   248
       *
mathieu@150
   249
       * Write the data delimited by start and end in internal buffer 
mathieu@150
   250
       * and avance the iterator position by the number of bytes
mathieu@150
   251
       * copied.
mathieu@150
   252
       * The input interators _must_ not point to the same Buffer as
mathieu@150
   253
       * we do to avoid overlapping copies. This is enforced 
mathieu@150
   254
       * in debug builds by asserts.
mathieu@150
   255
       */
mathieu@1461
   256
      void Write (Iterator start, Iterator end);
mathieu@9
   257
mathieu@150
   258
      /**
mathieu@150
   259
       * \return the byte read in the buffer.
mathieu@150
   260
       *
mathieu@150
   261
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   262
       * read.
mathieu@150
   263
       */
mathieu@1489
   264
      BUFFER_INLINE uint8_t  ReadU8 (void);
mathieu@150
   265
      /**
mathieu@150
   266
       * \return the two bytes read in the buffer.
mathieu@150
   267
       *
mathieu@150
   268
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   269
       * read.
mathieu@150
   270
       * The data is read in the format written by writeU16.
mathieu@150
   271
       */
mathieu@1461
   272
      uint16_t ReadU16 (void);
mathieu@150
   273
      /**
mathieu@150
   274
       * \return the four bytes read in the buffer.
mathieu@150
   275
       *
mathieu@150
   276
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   277
       * read.
mathieu@150
   278
       * The data is read in the format written by writeU32.
mathieu@150
   279
       */
mathieu@1461
   280
      uint32_t ReadU32 (void);
mathieu@150
   281
      /**
mathieu@150
   282
       * \return the eight bytes read in the buffer.
mathieu@150
   283
       *
mathieu@150
   284
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   285
       * read.
mathieu@150
   286
       * The data is read in the format written by writeU64.
mathieu@150
   287
       */
mathieu@1461
   288
      uint64_t ReadU64 (void);
mathieu@150
   289
      /**
mathieu@150
   290
       * \return the two bytes read in the buffer.
mathieu@150
   291
       *
mathieu@150
   292
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   293
       * read.
mathieu@150
   294
       * The data is read in network format and return in host format.
mathieu@150
   295
       */
mathieu@1461
   296
      uint16_t ReadNtohU16 (void);
mathieu@150
   297
      /**
mathieu@150
   298
       * \return the four bytes read in the buffer.
mathieu@150
   299
       *
mathieu@150
   300
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   301
       * read.
mathieu@150
   302
       * The data is read in network format and return in host format.
mathieu@150
   303
       */
mathieu@1461
   304
      uint32_t ReadNtohU32 (void);
mathieu@150
   305
      /**
mathieu@150
   306
       * \return the eight bytes read in the buffer.
mathieu@150
   307
       *
mathieu@150
   308
       * Read data and advance the Iterator by the number of bytes
mathieu@150
   309
       * read.
mathieu@150
   310
       * The data is read in network format and return in host format.
mathieu@150
   311
       */
mathieu@1461
   312
      uint64_t ReadNtohU64 (void);
mathieu@150
   313
      /**
mathieu@2792
   314
       * \return the two bytes read in the buffer.
mathieu@2792
   315
       *
mathieu@2792
   316
       * Read data and advance the Iterator by the number of bytes
mathieu@2792
   317
       * read.
mathieu@2792
   318
       * The data is read in network format and return in host format.
mathieu@2792
   319
       */
mathieu@2792
   320
      uint16_t ReadLsbtohU16 (void);
mathieu@2792
   321
      /**
mathieu@2792
   322
       * \return the four bytes read in the buffer.
mathieu@2792
   323
       *
mathieu@2792
   324
       * Read data and advance the Iterator by the number of bytes
mathieu@2792
   325
       * read.
mathieu@2792
   326
       * The data is read in network format and return in host format.
mathieu@2792
   327
       */
mathieu@2792
   328
      uint32_t ReadLsbtohU32 (void);
mathieu@2792
   329
      /**
mathieu@2792
   330
       * \return the eight bytes read in the buffer.
mathieu@2792
   331
       *
mathieu@2792
   332
       * Read data and advance the Iterator by the number of bytes
mathieu@2792
   333
       * read.
mathieu@2792
   334
       * The data is read in network format and return in host format.
mathieu@2792
   335
       */
mathieu@2792
   336
      uint64_t ReadLsbtohU64 (void);
mathieu@2792
   337
      /**
mathieu@150
   338
       * \param buffer buffer to copy data into
mathieu@150
   339
       * \param size number of bytes to copy
mathieu@150
   340
       *
mathieu@150
   341
       * Copy size bytes of data from the internal buffer to the
mathieu@150
   342
       * input buffer and avance the Iterator by the number of
mathieu@150
   343
       * bytes read.
mathieu@150
   344
       */
mathieu@1466
   345
      void Read (uint8_t *buffer, uint32_t size);
vincent@3363
   346
vincent@3363
   347
      /**
vincent@3363
   348
       * \brief Calculate the checksum.
vincent@3363
   349
       * \param size size of the buffer.
vincent@3363
   350
       * \return checksum
vincent@3363
   351
       */
vincent@3363
   352
      uint16_t CalculateIpChecksum(uint16_t size);
vincent@3363
   353
vincent@3363
   354
      /**
vincent@3363
   355
       * \brief Calculate the checksum.
vincent@3363
   356
       * \param size size of the buffer.
vincent@3363
   357
       * \param initialChecksum initial value
vincent@3363
   358
       * \return checksum
vincent@3363
   359
       */
vincent@3363
   360
      uint16_t CalculateIpChecksum(uint16_t size, uint32_t initialChecksum);
vincent@3363
   361
mathieu@3404
   362
      /**
mathieu@3404
   363
       * \returns the size of the underlying buffer we are iterating
mathieu@3404
   364
       */
mathieu@3404
   365
      uint32_t GetSize (void) const;
mathieu@3404
   366
mathieu@150
   367
  private:
mathieu@150
   368
      friend class Buffer;
mathieu@1463
   369
      Iterator (Buffer const*buffer);
mathieu@1463
   370
      Iterator (Buffer const*buffer, bool);
mathieu@1463
   371
      void Construct (const Buffer *buffer);
mathieu@1488
   372
      bool CheckNoZero (uint32_t start, uint32_t end) const;
mathieu@1488
   373
      bool Check (uint32_t i) const;
mathieu@1488
   374
mathieu@1491
   375
    /* offset in virtual bytes from the start of the data buffer to the
mathieu@1491
   376
     * start of the "virtual zero area".
mathieu@1491
   377
     */
mathieu@150
   378
      uint32_t m_zeroStart;
mathieu@1491
   379
    /* offset in virtual bytes from the start of the data buffer to the
mathieu@1491
   380
     * end of the "virtual zero area".
mathieu@1491
   381
     */
mathieu@150
   382
      uint32_t m_zeroEnd;
mathieu@1491
   383
    /* offset in virtual bytes from the start of the data buffer to the
mathieu@1491
   384
     * start of the data which can be read by this iterator
mathieu@1491
   385
     */
mathieu@1463
   386
      uint32_t m_dataStart;
mathieu@1491
   387
    /* offset in virtual bytes from the start of the data buffer to the
mathieu@1491
   388
     * end of the data which can be read by this iterator
mathieu@1491
   389
     */
mathieu@150
   390
      uint32_t m_dataEnd;
mathieu@1491
   391
    /* offset in virtual bytes from the start of the data buffer to the
mathieu@1491
   392
     * current position represented by this iterator.
mathieu@1491
   393
     */
mathieu@150
   394
      uint32_t m_current;
mathieu@1491
   395
    /* a pointer to the underlying byte buffer. All offsets are relative
mathieu@1491
   396
     * to this pointer.
mathieu@1491
   397
     */
mathieu@150
   398
      uint8_t *m_data;
mathieu@150
   399
  };
mathieu@9
   400
mathieu@150
   401
  /**
mathieu@150
   402
   * \return the number of bytes stored in this buffer.
mathieu@150
   403
   */
mathieu@1461
   404
  uint32_t GetSize (void) const;
mathieu@9
   405
mathieu@150
   406
  /**
mathieu@150
   407
   * \return a pointer to the start of the internal 
mathieu@150
   408
   * byte buffer.
mathieu@150
   409
   *
mathieu@150
   410
   * The returned pointer points to an area of
mathieu@150
   411
   * memory which is ns3::Buffer::GetSize () bytes big.
mathieu@150
   412
   * Please, try to never ever use this method. It is really
mathieu@150
   413
   * evil and is present only for a few specific uses.
mathieu@150
   414
   */
mathieu@150
   415
  uint8_t const*PeekData (void) const;
mathieu@9
   416
mathieu@150
   417
  /**
mathieu@150
   418
   * \param start size to reserve
mathieu@3035
   419
   * \returns true if the buffer needed resizing, false otherwise.
mathieu@150
   420
   *
mathieu@150
   421
   * Add bytes at the start of the Buffer. The
mathieu@150
   422
   * content of these bytes is undefined but debugging
mathieu@150
   423
   * builds initialize them to 0x33.
mathieu@150
   424
   * Any call to this method invalidates any Iterator
mathieu@150
   425
   * pointing to this Buffer.
mathieu@150
   426
   */
mathieu@3035
   427
  bool AddAtStart (uint32_t start);
mathieu@150
   428
  /**
mathieu@150
   429
   * \param end size to reserve
mathieu@3035
   430
   * \returns true if the buffer needed resizing, false otherwise.
mathieu@150
   431
   *
mathieu@150
   432
   * Add bytes at the end of the Buffer. The
mathieu@150
   433
   * content of these bytes is undefined but debugging
mathieu@150
   434
   * builds initialize them to 0x33.
mathieu@150
   435
   * Any call to this method invalidates any Iterator
mathieu@150
   436
   * pointing to this Buffer.
mathieu@150
   437
   */
mathieu@3035
   438
  bool AddAtEnd (uint32_t end);
mathieu@2992
   439
mathieu@3032
   440
  /**
mathieu@3032
   441
   * \param o the buffer to append to the end of this buffer.
mathieu@3032
   442
   *
mathieu@3032
   443
   * Add bytes at the end of the Buffer.
mathieu@3032
   444
   * Any call to this method invalidates any Iterator
mathieu@3032
   445
   * pointing to this Buffer.
mathieu@3032
   446
   */
mathieu@3035
   447
  void AddAtEnd (const Buffer &o);
mathieu@150
   448
  /**
mathieu@150
   449
   * \param start size to remove
mathieu@150
   450
   *
mathieu@150
   451
   * Remove bytes at the start of the Buffer.
mathieu@150
   452
   * Any call to this method invalidates any Iterator
mathieu@150
   453
   * pointing to this Buffer.
mathieu@150
   454
   */
mathieu@150
   455
  void RemoveAtStart (uint32_t start);
mathieu@150
   456
  /**
mathieu@150
   457
   * \param end size to remove
mathieu@150
   458
   *
mathieu@150
   459
   * Remove bytes at the end of the Buffer.
mathieu@150
   460
   * Any call to this method invalidates any Iterator
mathieu@150
   461
   * pointing to this Buffer.
mathieu@150
   462
   */
mathieu@150
   463
  void RemoveAtEnd (uint32_t end);
mathieu@9
   464
mathieu@150
   465
  /**
mathieu@150
   466
   * \param start offset from start of packet
mathieu@150
   467
   * \param length
mathieu@150
   468
   *
mathieu@150
   469
   * \return a fragment of size length starting at offset
mathieu@150
   470
   * start.
mathieu@150
   471
   */
mathieu@150
   472
  Buffer CreateFragment (uint32_t start, uint32_t length) const;
mathieu@9
   473
mathieu@150
   474
  /**
mathieu@150
   475
   * \return an Iterator which points to the
mathieu@150
   476
   * start of this Buffer.
mathieu@150
   477
   */
mathieu@1461
   478
  Buffer::Iterator Begin (void) const;
mathieu@150
   479
  /**
mathieu@150
   480
   * \return an Iterator which points to the
mathieu@150
   481
   * end of this Buffer.
mathieu@150
   482
   */
mathieu@1461
   483
  Buffer::Iterator End (void) const;
mathieu@9
   484
mathieu@1137
   485
  Buffer CreateFullCopy (void) const;
mathieu@823
   486
mathieu@3035
   487
  int32_t GetCurrentStartOffset (void) const;
mathieu@3035
   488
  int32_t GetCurrentEndOffset (void) const;
mathieu@3035
   489
nbaldo@4708
   490
  /** 
nbaldo@4708
   491
   * Copy the specified amount of data from the buffer to the given output stream.
nbaldo@4708
   492
   * 
nbaldo@4708
   493
   * @param os the output stream
nbaldo@4708
   494
   * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
nbaldo@4708
   495
   */
mathieu@4518
   496
  void CopyData (std::ostream *os, uint32_t size) const;
mathieu@4518
   497
mathieu@1461
   498
  Buffer (Buffer const &o);
mathieu@1461
   499
  Buffer &operator = (Buffer const &o);
mathieu@1461
   500
  Buffer ();
mathieu@1461
   501
  Buffer (uint32_t dataSize);
mathieu@1461
   502
  ~Buffer ();
mathieu@9
   503
private:
mathieu@9
   504
mathieu@1137
   505
  void TransformIntoRealBuffer (void) const;
mathieu@1474
   506
  bool CheckInternalState (void) const;
mathieu@1474
   507
  void Initialize (uint32_t zeroSize);
mathieu@1474
   508
  uint32_t GetInternalSize (void) const;
mathieu@1474
   509
  uint32_t GetInternalEnd (void) const;
mathieu@1474
   510
  static void Recycle (struct BufferData *data);
mathieu@1474
   511
  static struct BufferData *Create (uint32_t size);
mathieu@9
   512
mathieu@1491
   513
  /* This structure is described in the buffer.cc file.
mathieu@1491
   514
   */
mathieu@150
   515
  struct BufferData *m_data;
mathieu@1491
   516
#ifdef BUFFER_HEURISTICS
mathieu@1491
   517
  /* keep track of the maximum value of m_zeroAreaStart across
mathieu@1491
   518
   * the lifetime of a Buffer instance. This variable is used
mathieu@1491
   519
   * purely as a source of information for the heuristics which
mathieu@1491
   520
   * decide on the position of the zero area in new buffers.
mathieu@1491
   521
   * It is read from the Buffer destructor to update the global
mathieu@1491
   522
   * heuristic data and these global heuristic data are used from
mathieu@1491
   523
   * the Buffer constructor to choose an initial value for 
mathieu@1491
   524
   * m_zeroAreaStart.
mathieu@1491
   525
   * It is possible to disable all these heuristics by undefining the
mathieu@1491
   526
   * BUFFER_HEURISTICS macro at the top of buffer.h
mathieu@1491
   527
   */
mathieu@1474
   528
  uint32_t m_maxZeroAreaStart;
mathieu@1491
   529
#endif /* BUFFER_HEURISTICS */
mathieu@1491
   530
  /* offset to the start of the virtual zero area from the start 
mathieu@1491
   531
   * of m_data->m_data
mathieu@1491
   532
   */
mathieu@1473
   533
  uint32_t m_zeroAreaStart;
mathieu@1491
   534
  /* offset to the end of the virtual zero area from the start 
mathieu@1491
   535
   * of m_data->m_data
mathieu@1491
   536
   */
mathieu@1474
   537
  uint32_t m_zeroAreaEnd;
mathieu@1491
   538
  /* offset to the start of the data referenced by this Buffer
mathieu@1491
   539
   * instance from the start of m_data->m_data
mathieu@1491
   540
   */
mathieu@150
   541
  uint32_t m_start;
mathieu@1491
   542
  /* offset to the end of the data referenced by this Buffer
mathieu@1491
   543
   * instance from the start of m_data->m_data
mathieu@1491
   544
   */
mathieu@1470
   545
  uint32_t m_end;
mathieu@9
   546
};
mathieu@9
   547
mathieu@1461
   548
} // namespace ns3
mathieu@9
   549
mathieu@1488
   550
#ifdef BUFFER_USE_INLINE
mathieu@1488
   551
mathieu@1487
   552
#include "ns3/assert.h"
mathieu@3365
   553
#include <string.h>
mathieu@1487
   554
mathieu@1487
   555
namespace ns3 {
mathieu@1487
   556
mathieu@1487
   557
void
mathieu@1487
   558
Buffer::Iterator::WriteU8 (uint8_t data)
mathieu@1487
   559
{
mathieu@1488
   560
  NS_ASSERT (Check (m_current));
mathieu@1487
   561
mathieu@1487
   562
  if (m_current < m_zeroStart)
mathieu@1487
   563
    {
mathieu@1487
   564
      m_data[m_current] = data;
mathieu@1487
   565
      m_current++;
mathieu@1487
   566
    }
mathieu@1487
   567
  else
mathieu@1487
   568
    {
mathieu@1487
   569
      m_data[m_current - (m_zeroEnd-m_zeroStart)] = data;
mathieu@1487
   570
      m_current++;      
mathieu@1487
   571
    }
mathieu@1487
   572
}
mathieu@1487
   573
mathieu@1488
   574
void 
mathieu@1488
   575
Buffer::Iterator::WriteU8 (uint8_t  data, uint32_t len)
mathieu@1488
   576
{
mathieu@1490
   577
  NS_ASSERT (CheckNoZero (m_current, m_current + len));
mathieu@1488
   578
  if (m_current <= m_zeroStart)
mathieu@1488
   579
    {
mathieu@1488
   580
      memset (&(m_data[m_current]), data, len);
mathieu@1488
   581
      m_current += len;
mathieu@1488
   582
    }
mathieu@1488
   583
  else
mathieu@1488
   584
    {
mathieu@1488
   585
      uint8_t *buffer = &m_data[m_current - (m_zeroEnd-m_zeroStart)];
mathieu@1488
   586
      memset (buffer, data, len);
mathieu@1488
   587
      m_current += len;
mathieu@1488
   588
    }
mathieu@1488
   589
}
mathieu@1487
   590
mathieu@1489
   591
uint8_t  
mathieu@1489
   592
Buffer::Iterator::ReadU8 (void)
mathieu@1489
   593
{
mathieu@1489
   594
  NS_ASSERT (m_current >= m_dataStart &&
mathieu@1489
   595
             m_current <= m_dataEnd);
mathieu@1489
   596
mathieu@1489
   597
  if (m_current < m_zeroStart)
mathieu@1489
   598
    {
mathieu@1489
   599
      uint8_t data = m_data[m_current];
mathieu@1489
   600
      m_current++;
mathieu@1489
   601
      return data;
mathieu@1489
   602
    }
mathieu@1489
   603
  else if (m_current < m_zeroEnd)
mathieu@1489
   604
    {
mathieu@1489
   605
      m_current++;
mathieu@1489
   606
      return 0;
mathieu@1489
   607
    }
mathieu@1489
   608
  else
mathieu@1489
   609
    {
mathieu@1489
   610
      uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)];
mathieu@1489
   611
      m_current++;
mathieu@1489
   612
      return data;
mathieu@1489
   613
    }
mathieu@1489
   614
}
mathieu@1489
   615
mathieu@1489
   616
mathieu@1487
   617
} // namespace ns3
mathieu@1487
   618
mathieu@1488
   619
#endif /* BUFFER_USE_INLINE */
mathieu@1488
   620
mathieu@9
   621
#endif /* BUFFER_H */