A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
buffer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006,2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#ifndef BUFFER_H
9#define BUFFER_H
10
11#include "ns3/assert.h"
12
13#include <ostream>
14#include <stdint.h>
15#include <vector>
16
17#define BUFFER_FREE_LIST 1
18
19namespace ns3
20{
21
22/**
23 * @ingroup packet
24 *
25 * @brief automatically resized byte buffer
26 *
27 * This represents a buffer of bytes. Its size is
28 * automatically adjusted to hold any data prepended
29 * or appended by the user. Its implementation is optimized
30 * to ensure that the number of buffer resizes is minimized,
31 * by creating new Buffers of the maximum size ever used.
32 * The correct maximum size is learned at runtime during use by
33 * recording the maximum size of each packet.
34 *
35 * @internal
36 * The implementation of the Buffer class uses a COW (Copy On Write)
37 * technique to ensure that the underlying data buffer which holds
38 * the data bytes is shared among a lot of Buffer instances despite
39 * data being added or removed from them.
40 *
41 * When multiple Buffer instances hold a reference to the same
42 * underlying BufferData object, they must be able to detect when
43 * the operation they want to perform should trigger a copy of the
44 * BufferData. If the BufferData::m_count field is one, it means that
45 * there exist only one instance of Buffer which references the
46 * BufferData instance so, it is safe to modify it. It is also
47 * safe to modify the content of a BufferData if the modification
48 * falls outside of the "dirty area" defined by the BufferData.
49 * In every other case, the BufferData must be copied before
50 * being modified.
51 *
52 * To understand the way the Buffer::Add and Buffer::Remove methods
53 * work, you first need to understand the "virtual offsets" used to
54 * keep track of the content of buffers. Each Buffer instance
55 * contains real data bytes in its BufferData instance but it also
56 * contains "virtual zero data" which typically is used to represent
57 * application-level payload. No memory is allocated to store the
58 * zero bytes of application-level payload unless the user fragments
59 * a Buffer: this application-level payload is kept track of with
60 * a pair of integers which describe where in the buffer content
61 * the "virtual zero area" starts and ends.
62 *
63 * @verbatim
64 * ***: unused bytes
65 * xxx: bytes "added" at the front of the zero area
66 * ...: bytes "added" at the back of the zero area
67 * 000: virtual zero bytes
68 *
69 * Real byte buffer: |********xxxxxxxxxxxx.........*****|
70 * |--------^ m_start
71 * |-------------------^ m_zeroAreaStart
72 * |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart)
73 * Virtual byte buffer: |xxxxxxxxxxxx0000000000000.........|
74 * |--------^ m_start
75 * |--------------------^ m_zeroAreaStart
76 * |---------------------------------^ m_zeroAreaEnd
77 * |------------------------------------------^ m_end
78 * @endverbatim
79 *
80 * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end
81 */
82class Buffer
83{
84 public:
85 /**
86 * @brief iterator in a Buffer instance
87 */
89 {
90 public:
91 inline Iterator();
92 /**
93 * go forward by one byte
94 */
95 inline void Next();
96 /**
97 * go backward by one byte
98 */
99 inline void Prev();
100 /**
101 * @param delta number of bytes to go forward
102 */
103 inline void Next(uint32_t delta);
104 /**
105 * @param delta number of bytes to go backward
106 */
107 inline void Prev(uint32_t delta);
108 /**
109 * @param o the second iterator
110 * @return number of bytes included between the two iterators
111 *
112 * This method works only if the two iterators point
113 * to the same underlying buffer. Debug builds ensure
114 * this with an assert.
115 */
116 uint32_t GetDistanceFrom(const Iterator& o) const;
117
118 /**
119 * @return true if this iterator points to the end of the byte array.
120 * false otherwise.
121 */
122 bool IsEnd() const;
123 /**
124 * @return true if this iterator points to the start of the byte array.
125 * false otherwise.
126 */
127 bool IsStart() const;
128
129 /**
130 * @param data data to write in buffer
131 *
132 * Write the data in buffer and advance the iterator position
133 * by one byte.
134 */
135 inline void WriteU8(uint8_t data);
136 /**
137 * @param data data to write in buffer
138 * @param len number of times data must be written in buffer
139 *
140 * Write the data in buffer len times and advance the iterator position
141 * by len byte.
142 */
143 inline void WriteU8(uint8_t data, uint32_t len);
144 /**
145 * @param data data to write in buffer
146 *
147 * Write the data in buffer and advance the iterator position
148 * by two bytes. The format of the data written in the byte
149 * buffer is non-portable. We only ensure that readU16 will
150 * return exactly what we wrote with writeU16 if the program
151 * is run on the same machine.
152 */
153 void WriteU16(uint16_t data);
154 /**
155 * @param data data to write in buffer
156 *
157 * Write the data in buffer and advance the iterator position
158 * by four bytes. The format of the data written in the byte
159 * buffer is non-portable. We only ensure that readU32 will
160 * return exactly what we wrote with writeU32 if the program
161 * is run on the same machine.
162 */
163 void WriteU32(uint32_t data);
164 /**
165 * @param data data to write in buffer
166 *
167 * Write the data in buffer and advance the iterator position
168 * by eight bytes. The format of the data written in the byte
169 * buffer is non-portable. We only ensure that readU64 will
170 * return exactly what we wrote with writeU64 if the program
171 * is run on the same machine.
172 */
173 void WriteU64(uint64_t data);
174 /**
175 * @param data data to write in buffer
176 *
177 * Write the data in buffer and advance the iterator position
178 * by two bytes. The data is written in least significant byte order and the
179 * input data is expected to be in host order.
180 */
181 void WriteHtolsbU16(uint16_t data);
182 /**
183 * @param data data to write in buffer
184 *
185 * Write the data in buffer and advance the iterator position
186 * by four bytes. The data is written in least significant byte order and the
187 * input data is expected to be in host order.
188 */
190 /**
191 * @param data data to write in buffer
192 *
193 * Write the data in buffer and advance the iterator position
194 * by eight bytes. The data is written in least significant byte order and the
195 * input data is expected to be in host order.
196 */
197 void WriteHtolsbU64(uint64_t data);
198 /**
199 * @param data data to write in buffer
200 *
201 * Write the data in buffer and advance the iterator position
202 * by two bytes. The data is written in network order and the
203 * input data is expected to be in host order.
204 */
205 inline void WriteHtonU16(uint16_t data);
206 /**
207 * @param data data to write in buffer
208 *
209 * Write the data in buffer and advance the iterator position
210 * by four bytes. The data is written in network order and the
211 * input data is expected to be in host order.
212 */
213 inline void WriteHtonU32(uint32_t data);
214 /**
215 * @param data data to write in buffer
216 *
217 * Write the data in buffer and advance the iterator position
218 * by eight bytes. The data is written in network order and the
219 * input data is expected to be in host order.
220 */
221 void WriteHtonU64(uint64_t data);
222 /**
223 * @param buffer a byte buffer to copy in the internal buffer.
224 * @param size number of bytes to copy.
225 *
226 * Write the data in buffer and advance the iterator position
227 * by size bytes.
228 */
229 void Write(const uint8_t* buffer, uint32_t size);
230 /**
231 * @param start the start of the data to copy
232 * @param end the end of the data to copy
233 *
234 * Write the data delimited by start and end in internal buffer
235 * and advance the iterator position by the number of bytes
236 * copied.
237 * The input iterators _must_ not point to the same Buffer as
238 * we do to avoid overlapping copies. This is enforced
239 * in debug builds by asserts.
240 */
241 void Write(Iterator start, Iterator end);
242
243 /**
244 * @return the byte read in the buffer.
245 *
246 * Read data, but do not advance the Iterator read.
247 */
248 inline uint8_t PeekU8();
249
250 /**
251 * @return the byte read in the buffer.
252 *
253 * Read data and advance the Iterator by the number of bytes
254 * read.
255 */
256 inline uint8_t ReadU8();
257 /**
258 * @return the two bytes read in the buffer.
259 *
260 * Read data and advance the Iterator by the number of bytes
261 * read.
262 * The data is read in the format written by writeU16.
263 */
264 inline uint16_t ReadU16();
265 /**
266 * @return the four bytes read in the buffer.
267 *
268 * Read data and advance the Iterator by the number of bytes
269 * read.
270 * The data is read in the format written by writeU32.
271 */
273 /**
274 * @return the eight bytes read in the buffer.
275 *
276 * Read data and advance the Iterator by the number of bytes
277 * read.
278 * The data is read in the format written by writeU64.
279 */
280 uint64_t ReadU64();
281 /**
282 * @return the two bytes read in the buffer.
283 *
284 * Read data and advance the Iterator by the number of bytes
285 * read.
286 * The data is read in network format and returned in host format.
287 */
288 inline uint16_t ReadNtohU16();
289 /**
290 * @return the four bytes read in the buffer.
291 *
292 * Read data and advance the Iterator by the number of bytes
293 * read.
294 * The data is read in network format and returned in host format.
295 */
296 inline uint32_t ReadNtohU32();
297 /**
298 * @return the eight bytes read in the buffer.
299 *
300 * Read data and advance the Iterator by the number of bytes
301 * read.
302 * The data is read in network format and returned in host format.
303 */
304 uint64_t ReadNtohU64();
305 /**
306 * @return the two bytes read in the buffer.
307 *
308 * Read data and advance the Iterator by the number of bytes
309 * read.
310 * The data is read in least significant byte format and returned in host format.
311 */
312 uint16_t ReadLsbtohU16();
313 /**
314 * @return the four bytes read in the buffer.
315 *
316 * Read data and advance the Iterator by the number of bytes
317 * read.
318 * The data is read in least significant byte format and returned in host format.
319 */
321 /**
322 * @return the eight bytes read in the buffer.
323 *
324 * Read data and advance the Iterator by the number of bytes
325 * read.
326 * The data is read in least significant byte format and returned in host format.
327 */
328 uint64_t ReadLsbtohU64();
329 /**
330 * @param buffer buffer to copy data into
331 * @param size number of bytes to copy
332 *
333 * Copy size bytes of data from the internal buffer to the
334 * input buffer and advance the Iterator by the number of
335 * bytes read.
336 */
337 void Read(uint8_t* buffer, uint32_t size);
338
339 /**
340 * @param start start iterator of the buffer to copy data into
341 * @param size number of bytes to copy
342 *
343 * Copy size bytes of data from the internal buffer to the input buffer via
344 * the provided iterator and advance the Iterator by the number of bytes
345 * read.
346 */
347 inline void Read(Iterator start, uint32_t size);
348
349 /**
350 * @brief Calculate the checksum.
351 * @param size size of the buffer.
352 * @return checksum
353 */
354 uint16_t CalculateIpChecksum(uint16_t size);
355
356 /**
357 * @brief Calculate the checksum.
358 * @param size size of the buffer.
359 * @param initialChecksum initial value
360 * @return checksum
361 */
362 uint16_t CalculateIpChecksum(uint16_t size, uint32_t initialChecksum);
363
364 /**
365 * @returns the size of the underlying buffer we are iterating
366 */
367 uint32_t GetSize() const;
368
369 /**
370 * @returns the size left to read of the underlying buffer we are iterating
371 */
373
374 private:
375 /// Friend class
376 friend class Buffer;
377 /**
378 * Constructor - initializes the iterator to point to the buffer start
379 *
380 * @param buffer the buffer this iterator refers to
381 */
382 inline Iterator(const Buffer* buffer);
383 /**
384 * Constructor - initializes the iterator to point to the buffer end
385 *
386 * @param buffer the buffer this iterator refers to
387 * @param dummy not used param
388 */
389 inline Iterator(const Buffer* buffer, bool dummy);
390 /**
391 * Initializes the iterator values
392 *
393 * @param buffer the buffer this iterator refers to
394 */
395 inline void Construct(const Buffer* buffer);
396 /**
397 * Checks that the [start, end) is not in the "virtual zero area".
398 *
399 * @param start start buffer position
400 * @param end end buffer position
401 * @returns true if [start, end) is not in the "virtual zero area".
402 */
403 bool CheckNoZero(uint32_t start, uint32_t end) const;
404 /**
405 * Checks that the buffer position is not in the "virtual zero area".
406 *
407 * @param i buffer position
408 * @returns true if not in the "virtual zero area".
409 */
410 bool Check(uint32_t i) const;
411 /**
412 * @return the two bytes read in the buffer.
413 *
414 * Read data and advance the Iterator by the number of bytes
415 * read.
416 * The data is read in network format and returned in host format.
417 *
418 * @warning this is the slow version, please use ReadNtohU16 ()
419 */
420 uint16_t SlowReadNtohU16();
421 /**
422 * @return the four bytes read in the buffer.
423 *
424 * Read data and advance the Iterator by the number of bytes
425 * read.
426 * The data is read in network format and returned in host format.
427 *
428 * @warning this is the slow version, please use ReadNtohU32 ()
429 */
431 /**
432 * @brief Returns an appropriate message indicating a read error
433 * @returns the error message
434 */
435 std::string GetReadErrorMessage() const;
436 /**
437 * @brief Returns an appropriate message indicating a write error
438 *
439 * The message depends on the actual Buffer::Iterator status.
440 *
441 * @returns the error message
442 */
443 std::string GetWriteErrorMessage() const;
444
445 /**
446 * offset in virtual bytes from the start of the data buffer to the
447 * start of the "virtual zero area".
448 */
450 /**
451 * offset in virtual bytes from the start of the data buffer to the
452 * end of the "virtual zero area".
453 */
455 /**
456 * offset in virtual bytes from the start of the data buffer to the
457 * start of the data which can be read by this iterator
458 */
460 /**
461 * offset in virtual bytes from the start of the data buffer to the
462 * end of the data which can be read by this iterator
463 */
465 /**
466 * offset in virtual bytes from the start of the data buffer to the
467 * current position represented by this iterator.
468 */
470 /**
471 * a pointer to the underlying byte buffer. All offsets are relative
472 * to this pointer.
473 */
474 uint8_t* m_data;
475 };
476
477 /**
478 * @return the number of bytes stored in this buffer.
479 */
480 inline uint32_t GetSize() const;
481
482 /**
483 * @return a pointer to the start of the internal
484 * byte buffer.
485 *
486 * The returned pointer points to an area of
487 * memory which is ns3::Buffer::GetSize () bytes big.
488 * Please, try to never ever use this method. It is really
489 * evil and is present only for a few specific uses.
490 */
491 const uint8_t* PeekData() const;
492
493 /**
494 * @param start size to reserve
495 *
496 * Add bytes at the start of the Buffer. The
497 * content of these bytes is undefined but debugging
498 * builds initialize them to 0x33.
499 * Any call to this method invalidates any Iterator
500 * pointing to this Buffer.
501 */
502 void AddAtStart(uint32_t start);
503 /**
504 * @param end size to reserve
505 *
506 * Add bytes at the end of the Buffer. The
507 * content of these bytes is undefined but debugging
508 * builds initialize them to 0x33.
509 * Any call to this method invalidates any Iterator
510 * pointing to this Buffer.
511 */
512 void AddAtEnd(uint32_t end);
513
514 /**
515 * @param o the buffer to append to the end of this buffer.
516 *
517 * Add bytes at the end of the Buffer.
518 * Any call to this method invalidates any Iterator
519 * pointing to this Buffer.
520 */
521 void AddAtEnd(const Buffer& o);
522 /**
523 * @param start size to remove
524 *
525 * Remove bytes at the start of the Buffer.
526 * Any call to this method invalidates any Iterator
527 * pointing to this Buffer.
528 */
529 void RemoveAtStart(uint32_t start);
530 /**
531 * @param end size to remove
532 *
533 * Remove bytes at the end of the Buffer.
534 * Any call to this method invalidates any Iterator
535 * pointing to this Buffer.
536 */
537 void RemoveAtEnd(uint32_t end);
538
539 /**
540 * @param start offset from start of packet
541 * @param length
542 *
543 * @return a fragment of size length starting at offset
544 * start.
545 */
546 Buffer CreateFragment(uint32_t start, uint32_t length) const;
547
548 /**
549 * @return an Iterator which points to the
550 * start of this Buffer.
551 */
552 inline Buffer::Iterator Begin() const;
553 /**
554 * @return an Iterator which points to the
555 * end of this Buffer.
556 */
557 inline Buffer::Iterator End() const;
558
559 /**
560 * @brief Return the number of bytes required for serialization.
561 * @return the number of bytes.
562 */
564
565 /**
566 * @return zero if buffer not large enough
567 * @param buffer points to serialization buffer
568 * @param maxSize max number of bytes to write
569 *
570 * This buffer's contents are serialized into the raw
571 * character buffer parameter. Note: The zero length
572 * data is not copied entirely. Only the length of
573 * zero byte data is serialized.
574 */
575 uint32_t Serialize(uint8_t* buffer, uint32_t maxSize) const;
576
577 /**
578 * @return zero if a complete buffer is not deserialized
579 * @param buffer points to buffer for deserialization
580 * @param size number of bytes to deserialize
581 *
582 * The raw character buffer is deserialized and all the
583 * data is placed into this buffer.
584 */
585 uint32_t Deserialize(const uint8_t* buffer, uint32_t size);
586
587 /**
588 * Copy the specified amount of data from the buffer to the given output stream.
589 *
590 * @param os the output stream
591 * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
592 */
593 void CopyData(std::ostream* os, uint32_t size) const;
594
595 /**
596 * Copy the specified amount of data from the buffer to the given buffer.
597 *
598 * @param buffer the output buffer
599 * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
600 * @returns the amount of bytes copied
601 */
602 uint32_t CopyData(uint8_t* buffer, uint32_t size) const;
603
604 /**
605 * @brief Copy constructor
606 * @param o the buffer to copy
607 */
608 inline Buffer(const Buffer& o);
609 /**
610 * @brief Assignment operator
611 * @param o the buffer to copy
612 * @return a reference to the buffer
613 */
614 Buffer& operator=(const Buffer& o);
615 Buffer();
616 /**
617 * @brief Constructor
618 *
619 * The buffer will be initialized with zeroes up to its size.
620 *
621 * @param dataSize the buffer size
622 */
623 Buffer(uint32_t dataSize);
624 /**
625 * @brief Constructor
626 *
627 * If initialize is set to true, the buffer will be initialized
628 * with zeroes up to its size.
629 *
630 * @param dataSize the buffer size.
631 * @param initialize initialize the buffer with zeroes.
632 */
633 Buffer(uint32_t dataSize, bool initialize);
634 ~Buffer();
635
636 private:
637 /**
638 * This data structure is variable-sized through its last member whose size
639 * is determined at allocation time and stored in the m_size field.
640 *
641 * The so-called "dirty area" describes the area in the buffer which
642 * has been reserved and used by a user. Multiple Buffer instances
643 * may reference the same Buffer::Data object instance and may
644 * reference different parts of the underlying byte buffer. The
645 * "dirty area" is union of all the areas referenced by the Buffer
646 * instances which reference the same BufferData instance.
647 * New user data can be safely written only outside of the "dirty
648 * area" if the reference count is higher than 1 (that is, if
649 * more than one Buffer instance references the same BufferData).
650 */
651 struct Data
652 {
653 /**
654 * The reference count of an instance of this data structure.
655 * Each buffer which references an instance holds a count.
656 */
658 /**
659 * the size of the m_data field below.
660 */
662 /**
663 * offset from the start of the m_data field below to the
664 * start of the area in which user bytes were written.
665 */
667 /**
668 * offset from the start of the m_data field below to the
669 * end of the area in which user bytes were written.
670 */
672 /**
673 * The real data buffer holds _at least_ one byte.
674 * Its real size is stored in the m_size field.
675 */
676 uint8_t m_data[1];
677 };
678
679 /**
680 * @brief Create a full copy of the buffer, including
681 * all the internal structures.
682 *
683 * @returns a copy of the buffer
684 */
685 Buffer CreateFullCopy() const;
686
687 /**
688 * @brief Transform a "Virtual byte buffer" into a "Real byte buffer"
689 */
690 void TransformIntoRealBuffer() const;
691 /**
692 * @brief Checks the internal buffer structures consistency
693 *
694 * Used only for debugging purposes.
695 *
696 * @returns true if the buffer status is consistent.
697 */
698 bool CheckInternalState() const;
699
700 /**
701 * @brief Initializes the buffer with a number of zeroes.
702 *
703 * @param zeroSize the zeroes size
704 */
705 void Initialize(uint32_t zeroSize);
706
707 /**
708 * @brief Get the buffer real size.
709 * @warning The real size is the actual memory used by the buffer.
710 * @returns the memory used by the buffer.
711 */
713
714 /**
715 * @brief Get the buffer end position.
716 * @returns the buffer end index.
717 */
718 uint32_t GetInternalEnd() const;
719
720 /**
721 * @brief Recycle the buffer memory
722 * @param data the buffer data storage
723 */
724 static void Recycle(Buffer::Data* data);
725 /**
726 * @brief Create a buffer data storage
727 * @param size the storage size to create
728 * @returns a pointer to the created buffer storage
729 */
730 static Buffer::Data* Create(uint32_t size);
731 /**
732 * @brief Allocate a buffer data storage
733 * @param reqSize the storage size to create
734 * @returns a pointer to the allocated buffer storage
735 */
736 static Buffer::Data* Allocate(uint32_t reqSize);
737 /**
738 * @brief Deallocate the buffer memory
739 * @param data the buffer data storage
740 */
741 static void Deallocate(Buffer::Data* data);
742
743 Data* m_data; //!< the buffer data storage
744
745 /**
746 * keep track of the maximum value of m_zeroAreaStart across
747 * the lifetime of a Buffer instance. This variable is used
748 * purely as a source of information for the heuristics which
749 * decide on the position of the zero area in new buffers.
750 * It is read from the Buffer destructor to update the global
751 * heuristic data and these global heuristic data are used from
752 * the Buffer constructor to choose an initial value for
753 * m_zeroAreaStart.
754 */
756 /**
757 * location in a newly-allocated buffer where you should start
758 * writing data. i.e., m_start should be initialized to this
759 * value.
760 */
762
763 /**
764 * offset to the start of the virtual zero area from the start
765 * of m_data->m_data
766 */
768 /**
769 * offset to the end of the virtual zero area from the start
770 * of m_data->m_data
771 */
773 /**
774 * offset to the start of the data referenced by this Buffer
775 * instance from the start of m_data->m_data
776 */
778 /**
779 * offset to the end of the data referenced by this Buffer
780 * instance from the start of m_data->m_data
781 */
783
784#ifdef BUFFER_FREE_LIST
785 /// Container for buffer data
786 typedef std::vector<Buffer::Data*> FreeList;
787
788 /// Local static destructor structure
793
794 static uint32_t g_maxSize; //!< Max observed data size
795 static FreeList* g_freeList; //!< Buffer data container
796 static LocalStaticDestructor g_localStaticDestructor; //!< Local static destructor
797#endif
798};
799
800} // namespace ns3
801
802#include "ns3/assert.h"
803
804#include <cstring>
805
806namespace ns3
807{
808
810 : m_zeroStart(0),
811 m_zeroEnd(0),
812 m_dataStart(0),
813 m_dataEnd(0),
814 m_current(0),
815 m_data(nullptr)
816{
817}
818
820{
821 Construct(buffer);
822 m_current = m_dataStart;
823}
824
825Buffer::Iterator::Iterator(const Buffer* buffer, bool dummy)
826{
827 Construct(buffer);
828 m_current = m_dataEnd;
829}
830
831void
833{
834 m_zeroStart = buffer->m_zeroAreaStart;
835 m_zeroEnd = buffer->m_zeroAreaEnd;
836 m_dataStart = buffer->m_start;
837 m_dataEnd = buffer->m_end;
838 m_data = buffer->m_data->m_data;
839}
840
841void
843{
844 NS_ASSERT(m_current + 1 <= m_dataEnd);
845 m_current++;
846}
847
848void
850{
851 NS_ASSERT(m_current >= 1);
852 m_current--;
853}
854
855void
857{
858 NS_ASSERT(m_current + delta <= m_dataEnd);
859 m_current += delta;
860}
861
862void
864{
865 NS_ASSERT(m_current >= delta);
866 m_current -= delta;
867}
868
869void
871{
872 NS_ASSERT_MSG(Check(m_current), GetWriteErrorMessage());
873
874 if (m_current < m_zeroStart)
875 {
876 m_data[m_current] = data;
877 m_current++;
878 }
879 else
880 {
881 m_data[m_current - (m_zeroEnd - m_zeroStart)] = data;
882 m_current++;
883 }
884}
885
886void
888{
889 NS_ASSERT_MSG(CheckNoZero(m_current, m_current + len), GetWriteErrorMessage());
890 if (m_current <= m_zeroStart)
891 {
892 std::memset(&(m_data[m_current]), data, len);
893 m_current += len;
894 }
895 else
896 {
897 uint8_t* buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
898 std::memset(buffer, data, len);
899 m_current += len;
900 }
901}
902
903void
905{
906 NS_ASSERT_MSG(CheckNoZero(m_current, m_current + 2), GetWriteErrorMessage());
907 uint8_t* buffer;
908 if (m_current + 2 <= m_zeroStart)
909 {
910 buffer = &m_data[m_current];
911 }
912 else
913 {
914 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
915 }
916 buffer[0] = (data >> 8) & 0xff;
917 buffer[1] = (data >> 0) & 0xff;
918 m_current += 2;
919}
920
921void
923{
924 NS_ASSERT_MSG(CheckNoZero(m_current, m_current + 4), GetWriteErrorMessage());
925
926 uint8_t* buffer;
927 if (m_current + 4 <= m_zeroStart)
928 {
929 buffer = &m_data[m_current];
930 }
931 else
932 {
933 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
934 }
935 buffer[0] = (data >> 24) & 0xff;
936 buffer[1] = (data >> 16) & 0xff;
937 buffer[2] = (data >> 8) & 0xff;
938 buffer[3] = (data >> 0) & 0xff;
939 m_current += 4;
940}
941
942uint16_t
944{
945 uint8_t* buffer;
946 if (m_current + 2 <= m_zeroStart)
947 {
948 buffer = &m_data[m_current];
949 }
950 else if (m_current >= m_zeroEnd)
951 {
952 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
953 }
954 else
955 {
956 return SlowReadNtohU16();
957 }
958 uint16_t retval = 0;
959 retval |= buffer[0];
960 retval <<= 8;
961 retval |= buffer[1];
962 m_current += 2;
963 return retval;
964}
965
968{
969 uint8_t* buffer;
970 if (m_current + 4 <= m_zeroStart)
971 {
972 buffer = &m_data[m_current];
973 }
974 else if (m_current >= m_zeroEnd)
975 {
976 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
977 }
978 else
979 {
980 return SlowReadNtohU32();
981 }
982 uint32_t retval = 0;
983 retval |= buffer[0];
984 retval <<= 8;
985 retval |= buffer[1];
986 retval <<= 8;
987 retval |= buffer[2];
988 retval <<= 8;
989 retval |= buffer[3];
990 m_current += 4;
991 return retval;
992}
993
994uint8_t
996{
997 NS_ASSERT_MSG(m_current >= m_dataStart && m_current < m_dataEnd, GetReadErrorMessage());
998
999 if (m_current < m_zeroStart)
1000 {
1001 uint8_t data = m_data[m_current];
1002 return data;
1003 }
1004 else if (m_current < m_zeroEnd)
1005 {
1006 return 0;
1007 }
1008 else
1009 {
1010 uint8_t data = m_data[m_current - (m_zeroEnd - m_zeroStart)];
1011 return data;
1012 }
1013}
1014
1015uint8_t
1017{
1018 uint8_t ret = PeekU8();
1019 m_current++;
1020 return ret;
1021}
1022
1023uint16_t
1025{
1026 uint8_t byte0 = ReadU8();
1027 uint8_t byte1 = ReadU8();
1028 uint16_t data = byte1;
1029 data <<= 8;
1030 data |= byte0;
1031
1032 return data;
1033}
1034
1035void
1037{
1038 Buffer::Iterator end = *this;
1039 end.Next(size);
1040
1041 start.Write(*this, end);
1042}
1043
1055
1058{
1059 return m_end - m_start;
1060}
1061
1064{
1066 return Buffer::Iterator(this);
1067}
1068
1071{
1073 return Buffer::Iterator(this, false);
1074}
1075
1076} // namespace ns3
1077
1078#endif /* BUFFER_H */
iterator in a Buffer instance
Definition buffer.h:89
void WriteU64(uint64_t data)
Definition buffer.cc:870
uint32_t GetRemainingSize() const
Definition buffer.cc:1162
void Construct(const Buffer *buffer)
Initializes the iterator values.
Definition buffer.h:832
uint64_t ReadU64()
Definition buffer.cc:973
void WriteU32(uint32_t data)
Definition buffer.cc:857
uint32_t m_dataEnd
offset in virtual bytes from the start of the data buffer to the end of the data which can be read by...
Definition buffer.h:464
void WriteHtonU64(uint64_t data)
Definition buffer.cc:923
void WriteHtolsbU16(uint16_t data)
Definition buffer.cc:891
uint32_t m_dataStart
offset in virtual bytes from the start of the data buffer to the start of the data which can be read ...
Definition buffer.h:459
uint64_t ReadNtohU64()
Definition buffer.cc:1030
std::string GetReadErrorMessage() const
Returns an appropriate message indicating a read error.
Definition buffer.cc:1169
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition buffer.cc:1124
void WriteU8(uint8_t data)
Definition buffer.h:870
uint16_t SlowReadNtohU16()
Definition buffer.cc:1004
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition buffer.h:474
void WriteHtolsbU32(uint32_t data)
Definition buffer.cc:899
void Write(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:937
uint32_t m_zeroEnd
offset in virtual bytes from the start of the data buffer to the end of the "virtual zero area".
Definition buffer.h:454
uint16_t ReadLsbtohU16()
Definition buffer.cc:1053
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition buffer.cc:807
void WriteU16(uint16_t data)
Definition buffer.cc:848
uint32_t m_current
offset in virtual bytes from the start of the data buffer to the current position represented by this...
Definition buffer.h:469
uint32_t SlowReadNtohU32()
Definition buffer.cc:1015
void Read(uint8_t *buffer, uint32_t size)
Definition buffer.cc:1114
uint64_t ReadLsbtohU64()
Definition buffer.cc:1083
void WriteHtolsbU64(uint64_t data)
Definition buffer.cc:909
void WriteHtonU16(uint16_t data)
Definition buffer.h:904
uint32_t m_zeroStart
offset in virtual bytes from the start of the data buffer to the start of the "virtual zero area".
Definition buffer.h:449
bool CheckNoZero(uint32_t start, uint32_t end) const
Checks that the [start, end) is not in the "virtual zero area".
Definition buffer.cc:799
uint32_t ReadNtohU32()
Definition buffer.h:967
bool IsEnd() const
Definition buffer.cc:785
bool IsStart() const
Definition buffer.cc:792
uint32_t ReadU32()
Definition buffer.cc:955
void WriteHtonU32(uint32_t data)
Definition buffer.h:922
uint16_t ReadNtohU16()
Definition buffer.h:943
uint32_t GetDistanceFrom(const Iterator &o) const
Definition buffer.cc:769
void Prev()
go backward by one byte
Definition buffer.h:849
uint32_t GetSize() const
Definition buffer.cc:1155
uint16_t ReadU16()
Definition buffer.h:1024
std::string GetWriteErrorMessage() const
Returns an appropriate message indicating a write error.
Definition buffer.cc:1183
uint32_t ReadLsbtohU32()
Definition buffer.cc:1065
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
uint32_t GetSerializedSize() const
Return the number of bytes required for serialization.
Definition buffer.cc:555
std::vector< Buffer::Data * > FreeList
Container for buffer data.
Definition buffer.h:786
uint32_t GetInternalEnd() const
Get the buffer end position.
Definition buffer.cc:296
uint32_t m_end
offset to the end of the data referenced by this Buffer instance from the start of m_data->m_data
Definition buffer.h:782
static Buffer::Data * Allocate(uint32_t reqSize)
Allocate a buffer data storage.
Definition buffer.cc:155
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition buffer.cc:518
static FreeList * g_freeList
Buffer data container.
Definition buffer.h:795
Data * m_data
the buffer data storage
Definition buffer.h:743
static Buffer::Data * Create(uint32_t size)
Create a buffer data storage.
Definition buffer.cc:109
static uint32_t g_maxSize
Max observed data size.
Definition buffer.h:794
static LocalStaticDestructor g_localStaticDestructor
Local static destructor.
Definition buffer.h:796
uint32_t m_zeroAreaEnd
offset to the end of the virtual zero area from the start of m_data->m_data
Definition buffer.h:772
uint32_t m_maxZeroAreaStart
keep track of the maximum value of m_zeroAreaStart across the lifetime of a Buffer instance.
Definition buffer.h:755
static uint32_t g_recommendedStart
location in a newly-allocated buffer where you should start writing data.
Definition buffer.h:761
static void Deallocate(Buffer::Data *data)
Deallocate the buffer memory.
Definition buffer.cc:173
void CopyData(std::ostream *os, uint32_t size) const
Copy the specified amount of data from the buffer to the given output stream.
Definition buffer.cc:702
void RemoveAtEnd(uint32_t end)
Definition buffer.cc:482
void TransformIntoRealBuffer() const
Transform a "Virtual byte buffer" into a "Real byte buffer".
Definition buffer.cc:682
uint32_t GetSize() const
Definition buffer.h:1057
void AddAtStart(uint32_t start)
Definition buffer.cc:303
uint32_t GetInternalSize() const
Get the buffer real size.
Definition buffer.cc:289
Buffer::Iterator Begin() const
Definition buffer.h:1063
void AddAtEnd(uint32_t end)
Definition buffer.cc:349
Buffer::Iterator End() const
Definition buffer.h:1070
Buffer & operator=(const Buffer &o)
Assignment operator.
Definition buffer.cc:252
Buffer CreateFullCopy() const
Create a full copy of the buffer, including all the internal structures.
Definition buffer.cc:530
static void Recycle(Buffer::Data *data)
Recycle the buffer memory.
Definition buffer.cc:90
bool CheckInternalState() const
Checks the internal buffer structures consistency.
Definition buffer.cc:203
void Initialize(uint32_t zeroSize)
Initializes the buffer with a number of zeroes.
Definition buffer.cc:237
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:637
void RemoveAtStart(uint32_t start)
Definition buffer.cc:436
uint32_t m_zeroAreaStart
offset to the start of the virtual zero area from the start of m_data->m_data
Definition buffer.h:767
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Definition buffer.cc:571
const uint8_t * PeekData() const
Definition buffer.cc:692
uint32_t m_start
offset to the start of the data referenced by this Buffer instance from the start of m_data->m_data
Definition buffer.h:777
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t data[writeSize]
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition buffer.h:652
uint8_t m_data[1]
The real data buffer holds at least one byte.
Definition buffer.h:676
uint32_t m_dirtyEnd
offset from the start of the m_data field below to the end of the area in which user bytes were writt...
Definition buffer.h:671
uint32_t m_count
The reference count of an instance of this data structure.
Definition buffer.h:657
uint32_t m_size
the size of the m_data field below.
Definition buffer.h:661
uint32_t m_dirtyStart
offset from the start of the m_data field below to the start of the area in which user bytes were wri...
Definition buffer.h:666
Local static destructor structure.
Definition buffer.h:790