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