/usr/include/ns3/buffer.h is in libns3-dev 3.13+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 | /* -*- 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 noBUFFER_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.
*
* ***: 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
*
* 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 avance 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 avance 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 avance 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 avance 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 avance 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 avance the iterator position
* by two bytes. The data is written in network 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 avance 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 avance 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 avance 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.
*/
inline void WriteHtonU16 (uint16_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance 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 avance 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 avance 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 avance 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 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 return 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 return 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 return 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 network format and return 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 network format and return 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 network format and return 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 avance the Iterator by the number of
* bytes read.
*/
void Read (uint8_t *buffer, 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;
private:
friend class Buffer;
inline Iterator (Buffer const*buffer);
inline Iterator (Buffer const*buffer, bool);
inline void Construct (const Buffer *buffer);
bool CheckNoZero (uint32_t start, uint32_t end) const;
bool Check (uint32_t i) const;
uint16_t SlowReadNtohU16 (void);
uint32_t SlowReadNtohU32 (void);
std::string GetReadErrorMessage (void) const;
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
* \returns true if the buffer needed resizing, false otherwise.
*
* 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.
*/
bool AddAtStart (uint32_t start);
/**
* \param end size to reserve
* \returns true if the buffer needed resizing, false otherwise.
*
* 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.
*/
bool 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;
Buffer CreateFullCopy (void) const;
/**
* \return the number of bytes required for serialization
*/
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);
int32_t GetCurrentStartOffset (void) const;
int32_t GetCurrentEndOffset (void) const;
/**
* 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;
uint32_t CopyData (uint8_t *buffer, uint32_t size) const;
inline Buffer (Buffer const &o);
Buffer &operator = (Buffer const &o);
Buffer ();
Buffer (uint32_t dataSize);
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];
};
void TransformIntoRealBuffer (void) const;
bool CheckInternalState (void) const;
void Initialize (uint32_t zeroSize);
uint32_t GetInternalSize (void) const;
uint32_t GetInternalEnd (void) const;
static void Recycle (struct Buffer::Data *data);
static struct Buffer::Data *Create (uint32_t size);
static struct Buffer::Data *Allocate (uint32_t reqSize);
static void Deallocate (struct Buffer::Data *data);
struct Data *m_data;
/* 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
typedef std::vector<struct Buffer::Data*> FreeList;
struct LocalStaticDestructor
{
~LocalStaticDestructor ();
};
static uint32_t g_maxSize;
static FreeList *g_freeList;
static struct LocalStaticDestructor g_localStaticDestructor;
#endif
};
} // namespace ns3
#include "ns3/assert.h"
#include <string.h>
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)
{
memset (&(m_data[m_current]), data, len);
m_current += len;
}
else
{
uint8_t *buffer = &m_data[m_current - (m_zeroEnd-m_zeroStart)];
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];
}
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];
}
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::ReadU8 (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];
m_current++;
return data;
}
else if (m_current < m_zeroEnd)
{
m_current++;
return 0;
}
else
{
uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)];
m_current++;
return data;
}
}
uint16_t
Buffer::Iterator::ReadU16 (void)
{
uint8_t byte0 = ReadU8 ();
uint8_t byte1 = ReadU8 ();
uint16_t data = byte1;
data <<= 8;
data |= byte0;
return data;
}
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 */
|