A Discrete-Event Network Simulator
API
buffer.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "buffer.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 
24 #define LOG_INTERNAL_STATE(y) \
25  NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
26  ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
27  ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
28 
29 namespace {
30 
35 static struct Zeroes
36 {
37  Zeroes ()
38  : size (1000)
39  {
40  memset (buffer, 0, size);
41  }
42  char buffer[1000];
43  const uint32_t size;
44 } g_zeroes;
45 
46 }
47 
48 namespace ns3 {
49 
50 NS_LOG_COMPONENT_DEFINE ("Buffer");
51 
52 
53 uint32_t Buffer::g_recommendedStart = 0;
54 #ifdef BUFFER_FREE_LIST
55 /* The following macros are pretty evil but they are needed to allow us to
56  * keep track of 3 possible states for the g_freeList variable:
57  * - uninitialized means that no one has created a buffer yet
58  * so no one has created the associated free list (it is created
59  * on-demand when the first buffer is created)
60  * - initialized means that the free list exists and is valid
61  * - destroyed means that the static destructors of this compilation unit
62  * have run so, the free list has been cleared from its content
63  * The key is that in destroyed state, we are careful not re-create it
64  * which is a typical weakness of lazy evaluation schemes which use
65  * '0' as a special value to indicate both un-initialized and destroyed.
66  * Note that it is important to use '0' as the marker for un-initialized state
67  * because the variable holding this state information is initialized to zero
68  * which the compiler assigns to zero-memory which is initialized to _zero_
69  * before the constructors run so this ensures perfect handling of crazy
70  * constructor orderings.
71  */
72 #define MAGIC_DESTROYED (~(long) 0)
73 #define IS_UNINITIALIZED(x) (x == (Buffer::FreeList*)0)
74 #define IS_DESTROYED(x) (x == (Buffer::FreeList*)MAGIC_DESTROYED)
75 #define IS_INITIALIZED(x) (!IS_UNINITIALIZED (x) && !IS_DESTROYED (x))
76 #define DESTROYED ((Buffer::FreeList*)MAGIC_DESTROYED)
77 #define UNINITIALIZED ((Buffer::FreeList*)0)
78 uint32_t Buffer::g_maxSize = 0;
79 Buffer::FreeList *Buffer::g_freeList = 0;
80 struct Buffer::LocalStaticDestructor Buffer::g_localStaticDestructor;
81 
83 {
84  NS_LOG_FUNCTION (this);
86  {
87  for (Buffer::FreeList::iterator i = g_freeList->begin ();
88  i != g_freeList->end (); i++)
89  {
90  Buffer::Deallocate (*i);
91  }
92  delete g_freeList;
94  }
95 }
96 
97 void
98 Buffer::Recycle (struct Buffer::Data *data)
99 {
100  NS_LOG_FUNCTION (data);
101  NS_ASSERT (data->m_count == 0);
103  g_maxSize = std::max (g_maxSize, data->m_size);
104  /* feed into free list */
105  if (data->m_size < g_maxSize ||
107  g_freeList->size () > 1000)
108  {
109  Buffer::Deallocate (data);
110  }
111  else
112  {
114  g_freeList->push_back (data);
115  }
116 }
117 
118 Buffer::Data *
119 Buffer::Create (uint32_t dataSize)
120 {
121  NS_LOG_FUNCTION (dataSize);
122  /* try to find a buffer correctly sized. */
124  {
125  g_freeList = new Buffer::FreeList ();
126  }
127  else if (IS_INITIALIZED (g_freeList))
128  {
129  while (!g_freeList->empty ())
130  {
131  struct Buffer::Data *data = g_freeList->back ();
132  g_freeList->pop_back ();
133  if (data->m_size >= dataSize)
134  {
135  data->m_count = 1;
136  return data;
137  }
138  Buffer::Deallocate (data);
139  }
140  }
141  struct Buffer::Data *data = Buffer::Allocate (dataSize);
142  NS_ASSERT (data->m_count == 1);
143  return data;
144 }
145 #else /* BUFFER_FREE_LIST */
146 void
147 Buffer::Recycle (struct Buffer::Data *data)
148 {
149  NS_LOG_FUNCTION (data);
150  NS_ASSERT (data->m_count == 0);
151  Deallocate (data);
152 }
153 
154 Buffer::Data *
155 Buffer::Create (uint32_t size)
156 {
157  NS_LOG_FUNCTION (size);
158  return Allocate (size);
159 }
160 #endif /* BUFFER_FREE_LIST */
161 
162 struct Buffer::Data *
163 Buffer::Allocate (uint32_t reqSize)
164 {
165  NS_LOG_FUNCTION (reqSize);
166  if (reqSize == 0)
167  {
168  reqSize = 1;
169  }
170  NS_ASSERT (reqSize >= 1);
171  uint32_t size = reqSize - 1 + sizeof (struct Buffer::Data);
172  uint8_t *b = new uint8_t [size];
173  struct Buffer::Data *data = reinterpret_cast<struct Buffer::Data*>(b);
174  data->m_size = reqSize;
175  data->m_count = 1;
176  return data;
177 }
178 
179 void
180 Buffer::Deallocate (struct Buffer::Data *data)
181 {
182  NS_LOG_FUNCTION (data);
183  NS_ASSERT (data->m_count == 0);
184  uint8_t *buf = reinterpret_cast<uint8_t *> (data);
185  delete [] buf;
186 }
187 
188 Buffer::Buffer ()
189 {
190  NS_LOG_FUNCTION (this);
191  Initialize (0);
192 }
193 
194 Buffer::Buffer (uint32_t dataSize)
195 {
196  NS_LOG_FUNCTION (this << dataSize);
197  Initialize (dataSize);
198 }
199 
200 Buffer::Buffer (uint32_t dataSize, bool initialize)
201 {
202  NS_LOG_FUNCTION (this << dataSize << initialize);
203  if (initialize == true)
204  {
205  Initialize (dataSize);
206  }
207 }
208 
209 bool
210 Buffer::CheckInternalState (void) const
211 {
212  NS_LOG_FUNCTION (this);
213 #if 0
214  // If you want to modify any code in this file, enable this checking code.
215  // Otherwise, there is not much point is enabling it because the
216  // current implementation has been fairly seriously tested and the cost
217  // of this constant checking is pretty high, even for a debug build.
218  bool offsetsOk =
219  m_start <= m_zeroAreaStart &&
220  m_zeroAreaStart <= m_zeroAreaEnd &&
221  m_zeroAreaEnd <= m_end;
222  bool dirtyOk =
223  m_start >= m_data->m_dirtyStart &&
224  m_end <= m_data->m_dirtyEnd;
225  bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
226  m_start <= m_data->m_size &&
227  m_zeroAreaStart <= m_data->m_size;
228 
229  bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
230  if (!ok)
231  {
232  LOG_INTERNAL_STATE ("check " << this <<
233  ", " << (offsetsOk ? "true" : "false") <<
234  ", " << (dirtyOk ? "true" : "false") <<
235  ", " << (internalSizeOk ? "true" : "false") << " ");
236  }
237  return ok;
238 #else
239  return true;
240 #endif
241 }
242 
243 void
244 Buffer::Initialize (uint32_t zeroSize)
245 {
246  NS_LOG_FUNCTION (this << zeroSize);
247  m_data = Buffer::Create (0);
248  m_start = std::min (m_data->m_size, g_recommendedStart);
249  m_maxZeroAreaStart = m_start;
250  m_zeroAreaStart = m_start;
251  m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
252  m_end = m_zeroAreaEnd;
253  m_data->m_dirtyStart = m_start;
254  m_data->m_dirtyEnd = m_end;
255  NS_ASSERT (CheckInternalState ());
256 }
257 
258 Buffer &
259 Buffer::operator = (Buffer const&o)
260 {
261  NS_ASSERT (CheckInternalState ());
262  if (m_data != o.m_data)
263  {
264  // not assignment to self.
265  m_data->m_count--;
266  if (m_data->m_count == 0)
267  {
268  Recycle (m_data);
269  }
270  m_data = o.m_data;
271  m_data->m_count++;
272  }
273  g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart);
274  m_maxZeroAreaStart = o.m_maxZeroAreaStart;
275  m_zeroAreaStart = o.m_zeroAreaStart;
276  m_zeroAreaEnd = o.m_zeroAreaEnd;
277  m_start = o.m_start;
278  m_end = o.m_end;
279  NS_ASSERT (CheckInternalState ());
280  return *this;
281 }
282 
283 Buffer::~Buffer ()
284 {
285  NS_LOG_FUNCTION (this);
286  NS_ASSERT (CheckInternalState ());
287  g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart);
288  m_data->m_count--;
289  if (m_data->m_count == 0)
290  {
291  Recycle (m_data);
292  }
293 }
294 
295 uint32_t
296 Buffer::GetInternalSize (void) const
297 {
298  NS_LOG_FUNCTION (this);
299  return m_zeroAreaStart - m_start + m_end - m_zeroAreaEnd;
300 }
301 uint32_t
302 Buffer::GetInternalEnd (void) const
303 {
304  NS_LOG_FUNCTION (this);
305  return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
306 }
307 
308 void
309 Buffer::AddAtStart (uint32_t start)
310 {
311  NS_LOG_FUNCTION (this << start);
312  NS_ASSERT (CheckInternalState ());
313  bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
314  if (m_start >= start && !isDirty)
315  {
316  /* enough space in the buffer and not dirty.
317  * To add: |..|
318  * Before: |*****---------***|
319  * After: |***..---------***|
320  */
321  NS_ASSERT (m_data->m_count == 1 || m_start == m_data->m_dirtyStart);
322  m_start -= start;
323  // update dirty area
324  m_data->m_dirtyStart = m_start;
325  }
326  else
327  {
328  uint32_t newSize = GetInternalSize () + start;
329  struct Buffer::Data *newData = Buffer::Create (newSize);
330  memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
331  m_data->m_count--;
332  if (m_data->m_count == 0)
333  {
334  Buffer::Recycle (m_data);
335  }
336  m_data = newData;
337 
338  int32_t delta = start - m_start;
339  m_start += delta;
340  m_zeroAreaStart += delta;
341  m_zeroAreaEnd += delta;
342  m_end += delta;
343  m_start -= start;
344 
345  // update dirty area
346  m_data->m_dirtyStart = m_start;
347  m_data->m_dirtyEnd = m_end;
348  }
349  m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart);
350  LOG_INTERNAL_STATE ("add start=" << start << ", ");
351  NS_ASSERT (CheckInternalState ());
352 }
353 void
354 Buffer::AddAtEnd (uint32_t end)
355 {
356  NS_LOG_FUNCTION (this << end);
357  NS_ASSERT (CheckInternalState ());
358  bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
359  if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
360  {
361  /* enough space in buffer and not dirty
362  * Add: |...|
363  * Before: |**----*****|
364  * After: |**----...**|
365  */
366  NS_ASSERT (m_data->m_count == 1 || m_end == m_data->m_dirtyEnd);
367  m_end += end;
368  // update dirty area.
369  m_data->m_dirtyEnd = m_end;
370  }
371  else
372  {
373  uint32_t newSize = GetInternalSize () + end;
374  struct Buffer::Data *newData = Buffer::Create (newSize);
375  memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
376  m_data->m_count--;
377  if (m_data->m_count == 0)
378  {
379  Buffer::Recycle (m_data);
380  }
381  m_data = newData;
382 
383  int32_t delta = -m_start;
384  m_zeroAreaStart += delta;
385  m_zeroAreaEnd += delta;
386  m_end += delta;
387  m_start += delta;
388  m_end += end;
389 
390  // update dirty area
391  m_data->m_dirtyStart = m_start;
392  m_data->m_dirtyEnd = m_end;
393  }
394  m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart);
395  LOG_INTERNAL_STATE ("add end=" << end << ", ");
396  NS_ASSERT (CheckInternalState ());
397 }
398 
399 void
400 Buffer::AddAtEnd (const Buffer &o)
401 {
402  NS_LOG_FUNCTION (this << &o);
403  if (m_data->m_count == 1 &&
404  m_end == m_zeroAreaEnd &&
405  m_end == m_data->m_dirtyEnd &&
406  o.m_start == o.m_zeroAreaStart &&
407  o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
408  {
414  uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
415  m_zeroAreaEnd += zeroSize;
416  m_end = m_zeroAreaEnd;
417  m_data->m_dirtyEnd = m_zeroAreaEnd;
418  uint32_t endData = o.m_end - o.m_zeroAreaEnd;
419  AddAtEnd (endData);
420  Buffer::Iterator dst = End ();
421  dst.Prev (endData);
422  Buffer::Iterator src = o.End ();
423  src.Prev (endData);
424  dst.Write (src, o.End ());
425  NS_ASSERT (CheckInternalState ());
426  return;
427  }
428 
429  Buffer dst = CreateFullCopy ();
430  Buffer src = o.CreateFullCopy ();
431 
432  dst.AddAtEnd (src.GetSize ());
433  Buffer::Iterator destStart = dst.End ();
434  destStart.Prev (src.GetSize ());
435  destStart.Write (src.Begin (), src.End ());
436  *this = dst;
437  NS_ASSERT (CheckInternalState ());
438 }
439 
440 void
441 Buffer::RemoveAtStart (uint32_t start)
442 {
443  NS_LOG_FUNCTION (this << start);
444  NS_ASSERT (CheckInternalState ());
445  uint32_t newStart = m_start + start;
446  if (newStart <= m_zeroAreaStart)
447  {
448  /* only remove start of buffer
449  */
450  m_start = newStart;
451  }
452  else if (newStart <= m_zeroAreaEnd)
453  {
454  /* remove start of buffer _and_ start of zero area
455  */
456  uint32_t delta = newStart - m_zeroAreaStart;
457  m_start = m_zeroAreaStart;
458  m_zeroAreaEnd -= delta;
459  m_end -= delta;
460  }
461  else if (newStart <= m_end)
462  {
463  /* remove start of buffer, complete zero area, and part
464  * of end of buffer
465  */
466  NS_ASSERT (m_end >= start);
467  uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
468  m_start = newStart - zeroSize;
469  m_end -= zeroSize;
470  m_zeroAreaStart = m_start;
471  m_zeroAreaEnd = m_start;
472  }
473  else
474  {
475  /* remove all buffer */
476  m_end -= m_zeroAreaEnd - m_zeroAreaStart;
477  m_start = m_end;
478  m_zeroAreaEnd = m_end;
479  m_zeroAreaStart = m_end;
480  }
481  m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart);
482  LOG_INTERNAL_STATE ("rem start=" << start << ", ");
483  NS_ASSERT (CheckInternalState ());
484 }
485 void
486 Buffer::RemoveAtEnd (uint32_t end)
487 {
488  NS_LOG_FUNCTION (this << end);
489  NS_ASSERT (CheckInternalState ());
490  uint32_t newEnd = m_end - std::min (end, m_end - m_start);
491  if (newEnd > m_zeroAreaEnd)
492  {
493  /* remove part of end of buffer */
494  m_end = newEnd;
495  }
496  else if (newEnd > m_zeroAreaStart)
497  {
498  /* remove end of buffer, part of zero area */
499  m_end = newEnd;
500  m_zeroAreaEnd = newEnd;
501  }
502  else if (newEnd > m_start)
503  {
504  /* remove end of buffer, zero area, part of start of buffer */
505  m_end = newEnd;
506  m_zeroAreaEnd = newEnd;
507  m_zeroAreaStart = newEnd;
508  }
509  else
510  {
511  /* remove all buffer */
512  m_end = m_start;
513  m_zeroAreaEnd = m_start;
514  m_zeroAreaStart = m_start;
515  }
516  m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart);
517  LOG_INTERNAL_STATE ("rem end=" << end << ", ");
518  NS_ASSERT (CheckInternalState ());
519 }
520 
521 Buffer
522 Buffer::CreateFragment (uint32_t start, uint32_t length) const
523 {
524  NS_LOG_FUNCTION (this << start << length);
525  NS_ASSERT (CheckInternalState ());
526  Buffer tmp = *this;
527  tmp.RemoveAtStart (start);
528  tmp.RemoveAtEnd (GetSize () - (start + length));
529  NS_ASSERT (CheckInternalState ());
530  return tmp;
531 }
532 
533 Buffer
534 Buffer::CreateFullCopy (void) const
535 {
536  NS_LOG_FUNCTION (this);
537  NS_ASSERT (CheckInternalState ());
538  if (m_zeroAreaEnd - m_zeroAreaStart != 0)
539  {
540  Buffer tmp;
541  tmp.AddAtStart (m_zeroAreaEnd - m_zeroAreaStart);
542  tmp.Begin ().WriteU8 (0, m_zeroAreaEnd - m_zeroAreaStart);
543  uint32_t dataStart = m_zeroAreaStart - m_start;
544  tmp.AddAtStart (dataStart);
545  tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
546  uint32_t dataEnd = m_end - m_zeroAreaEnd;
547  tmp.AddAtEnd (dataEnd);
548  Buffer::Iterator i = tmp.End ();
549  i.Prev (dataEnd);
550  i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
551  NS_ASSERT (tmp.CheckInternalState ());
552  return tmp;
553  }
554  NS_ASSERT (CheckInternalState ());
555  return *this;
556 }
557 
558 uint32_t
559 Buffer::GetSerializedSize (void) const
560 {
561  NS_LOG_FUNCTION (this);
562  uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
563  uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
564 
565  // total size 4-bytes for dataStart length
566  // + X number of bytes for dataStart
567  // + 4-bytes for dataEnd length
568  // + X number of bytes for dataEnd
569  uint32_t sz = sizeof (uint32_t)
570  + sizeof (uint32_t)
571  + dataStart
572  + sizeof (uint32_t)
573  + dataEnd;
574 
575  return sz;
576 }
577 
578 uint32_t
579 Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
580 {
581  NS_LOG_FUNCTION (this << &buffer << maxSize);
582  uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
583  uint32_t size = 0;
584 
585  // Add the zero data length
586  if (size + 4 <= maxSize)
587  {
588  size += 4;
589  *p++ = m_zeroAreaEnd - m_zeroAreaStart;
590  }
591  else
592  {
593  return 0;
594  }
595 
596  // Add the length of actual start data
597  uint32_t dataStartLength = m_zeroAreaStart - m_start;
598  if (size + 4 <= maxSize)
599  {
600  size += 4;
601  *p++ = dataStartLength;
602  }
603  else
604  {
605  return 0;
606  }
607 
608  // Add the actual data
609  if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
610  {
611  size += (dataStartLength + 3) & (~3);
612  memcpy (p, m_data->m_data + m_start, dataStartLength);
613  p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
614  }
615  else
616  {
617  return 0;
618  }
619 
620  // Add the length of the actual end data
621  uint32_t dataEndLength = m_end - m_zeroAreaEnd;
622  if (size + 4 <= maxSize)
623  {
624  size += 4;
625  *p++ = dataEndLength;
626  }
627  else
628  {
629  return 0;
630  }
631 
632  // Add the actual data
633  if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
634  {
635  // The following line is unnecessary.
636  // size += (dataEndLength + 3) & (~3);
637  memcpy (p, m_data->m_data+m_zeroAreaStart, dataEndLength);
638  // The following line is unnecessary.
639  // p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
640  }
641  else
642  {
643  return 0;
644  }
645 
646  // Serialized everything successfully
647  return 1;
648 }
649 
650 uint32_t
651 Buffer::Deserialize (const uint8_t *buffer, uint32_t size)
652 {
653  NS_LOG_FUNCTION (this << &buffer << size);
654  const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
655  uint32_t sizeCheck = size-4;
656 
657  NS_ASSERT (sizeCheck >= 4);
658  uint32_t zeroDataLength = *p++;
659  sizeCheck -= 4;
660 
661  // Create zero bytes
662  Initialize (zeroDataLength);
663 
664  // Add start data
665  NS_ASSERT (sizeCheck >= 4);
666  uint32_t dataStartLength = *p++;
667  sizeCheck -= 4;
668  AddAtStart (dataStartLength);
669 
670  NS_ASSERT (sizeCheck >= dataStartLength);
671  Begin ().Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataStartLength);
672  p += (((dataStartLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
673  sizeCheck -= ((dataStartLength+3)&(~3));
674 
675  // Add end data
676  NS_ASSERT (sizeCheck >= 4);
677  uint32_t dataEndLength = *p++;
678  sizeCheck -= 4;
679  AddAtEnd (dataEndLength);
680 
681  NS_ASSERT (sizeCheck >= dataEndLength);
682  Buffer::Iterator tmp = End ();
683  tmp.Prev (dataEndLength);
684  tmp.Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataEndLength);
685  // The following line is unnecessary.
686  // p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
687  sizeCheck -= ((dataEndLength+3)&(~3));
688 
689  NS_ASSERT (sizeCheck == 0);
690  // return zero if buffer did not
691  // contain a complete message
692  return (sizeCheck != 0) ? 0 : 1;
693 }
694 
695 
696 void
697 Buffer::TransformIntoRealBuffer (void) const
698 {
699  NS_LOG_FUNCTION (this);
700  NS_ASSERT (CheckInternalState ());
701  Buffer tmp = CreateFullCopy ();
702  *const_cast<Buffer *> (this) = tmp;
703  NS_ASSERT (CheckInternalState ());
704 }
705 
706 
707 uint8_t const*
708 Buffer::PeekData (void) const
709 {
710  NS_LOG_FUNCTION (this);
711  NS_ASSERT (CheckInternalState ());
712  TransformIntoRealBuffer ();
713  NS_ASSERT (CheckInternalState ());
714  return m_data->m_data + m_start;
715 }
716 
717 void
718 Buffer::CopyData (std::ostream *os, uint32_t size) const
719 {
720  NS_LOG_FUNCTION (this << &os << size);
721  if (size > 0)
722  {
723  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
724  os->write ((const char*)(m_data->m_data + m_start), tmpsize);
725  if (size > tmpsize)
726  {
727  size -= m_zeroAreaStart-m_start;
728  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
729  uint32_t left = tmpsize;
730  while (left > 0)
731  {
732  uint32_t toWrite = std::min (left, g_zeroes.size);
733  os->write (g_zeroes.buffer, toWrite);
734  left -= toWrite;
735  }
736  if (size > tmpsize)
737  {
738  size -= tmpsize;
739  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
740  os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
741  }
742  }
743  }
744 }
745 
746 uint32_t
747 Buffer::CopyData (uint8_t *buffer, uint32_t size) const
748 {
749  NS_LOG_FUNCTION (this << &buffer << size);
750  uint32_t originalSize = size;
751  if (size > 0)
752  {
753  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
754  memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
755  buffer += tmpsize;
756  size -= tmpsize;
757  if (size > 0)
758  {
759  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
760  uint32_t left = tmpsize;
761  while (left > 0)
762  {
763  uint32_t toWrite = std::min (left, g_zeroes.size);
764  memcpy (buffer, g_zeroes.buffer, toWrite);
765  left -= toWrite;
766  buffer += toWrite;
767  }
768  size -= tmpsize;
769  if (size > 0)
770  {
771  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
772  memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
773  size -= tmpsize;
774  }
775  }
776  }
777  return originalSize - size;
778 }
779 
780 /******************************************************
781  * The buffer iterator below.
782  ******************************************************/
783 
784 
785 uint32_t
786 Buffer::Iterator::GetDistanceFrom (Iterator const &o) const
787 {
788  NS_LOG_FUNCTION (this << &o);
789  NS_ASSERT (m_data == o.m_data);
790  int32_t diff = m_current - o.m_current;
791  if (diff < 0)
792  {
793  return -diff;
794  }
795  else
796  {
797  return diff;
798  }
799 }
800 
801 bool
802 Buffer::Iterator::IsEnd (void) const
803 {
804  NS_LOG_FUNCTION (this);
805  return m_current == m_dataEnd;
806 }
807 bool
808 Buffer::Iterator::IsStart (void) const
809 {
810  NS_LOG_FUNCTION (this);
811  return m_current == m_dataStart;
812 }
813 
814 bool
815 Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const
816 {
817  NS_LOG_FUNCTION (this << &start << &end);
818  for (uint32_t i = start; i < end; i++)
819  {
820  if (!Check (i))
821  {
822  return false;
823  }
824  }
825  return true;
826 }
827 bool
828 Buffer::Iterator::Check (uint32_t i) const
829 {
830  NS_LOG_FUNCTION (this << &i);
831  return i >= m_dataStart &&
832  !(i >= m_zeroStart && i < m_zeroEnd) &&
833  i <= m_dataEnd;
834 }
835 
836 
837 void
838 Buffer::Iterator::Write (Iterator start, Iterator end)
839 {
840  NS_LOG_FUNCTION (this << &start << &end);
841  NS_ASSERT (start.m_data == end.m_data);
842  NS_ASSERT (start.m_current <= end.m_current);
843  NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
844  NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
845  NS_ASSERT (m_data != start.m_data);
846  uint32_t size = end.m_current - start.m_current;
847  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + size),
848  GetWriteErrorMessage ());
849  if (start.m_current <= start.m_zeroStart)
850  {
851  uint32_t toCopy = std::min (size, start.m_zeroStart - start.m_current);
852  memcpy (&m_data[m_current], &start.m_data[start.m_current], toCopy);
853  start.m_current += toCopy;
854  m_current += toCopy;
855  size -= toCopy;
856  }
857  if (start.m_current <= start.m_zeroEnd)
858  {
859  uint32_t toCopy = std::min (size, start.m_zeroEnd - start.m_current);
860  memset (&m_data[m_current], 0, toCopy);
861  start.m_current += toCopy;
862  m_current += toCopy;
863  size -= toCopy;
864  }
865  uint32_t toCopy = std::min (size, start.m_dataEnd - start.m_current);
866  uint8_t *from = &start.m_data[start.m_current - (start.m_zeroEnd-start.m_zeroStart)];
867  uint8_t *to = &m_data[m_current];
868  memcpy (to, from, toCopy);
869  m_current += toCopy;
870 }
871 
872 void
873 Buffer::Iterator::WriteU16 (uint16_t data)
874 {
875  NS_LOG_FUNCTION (this << data);
876  WriteU8 (data & 0xff);
877  data >>= 8;
878  WriteU8 (data & 0xff);
879 }
880 void
881 Buffer::Iterator::WriteU32 (uint32_t data)
882 {
883  NS_LOG_FUNCTION (this << data);
884  WriteU8 (data & 0xff);
885  data >>= 8;
886  WriteU8 (data & 0xff);
887  data >>= 8;
888  WriteU8 (data & 0xff);
889  data >>= 8;
890  WriteU8 (data & 0xff);
891 }
892 void
893 Buffer::Iterator::WriteU64 (uint64_t data)
894 {
895  NS_LOG_FUNCTION (this << data);
896  WriteU8 (data & 0xff);
897  data >>= 8;
898  WriteU8 (data & 0xff);
899  data >>= 8;
900  WriteU8 (data & 0xff);
901  data >>= 8;
902  WriteU8 (data & 0xff);
903  data >>= 8;
904  WriteU8 (data & 0xff);
905  data >>= 8;
906  WriteU8 (data & 0xff);
907  data >>= 8;
908  WriteU8 (data & 0xff);
909  data >>= 8;
910  WriteU8 (data & 0xff);
911 }
912 void
913 Buffer::Iterator::WriteHtolsbU16 (uint16_t data)
914 {
915  NS_LOG_FUNCTION (this << data);
916  WriteU8 ((data >> 0) & 0xff);
917  WriteU8 ((data >> 8) & 0xff);
918 }
919 void
920 Buffer::Iterator::WriteHtolsbU32 (uint32_t data)
921 {
922  NS_LOG_FUNCTION (this << data);
923  WriteU8 ((data >> 0) & 0xff);
924  WriteU8 ((data >> 8) & 0xff);
925  WriteU8 ((data >> 16) & 0xff);
926  WriteU8 ((data >> 24) & 0xff);
927 }
928 void
929 Buffer::Iterator::WriteHtolsbU64 (uint64_t data)
930 {
931  NS_LOG_FUNCTION (this << data);
932  WriteU8 ((data >> 0) & 0xff);
933  WriteU8 ((data >> 8) & 0xff);
934  WriteU8 ((data >> 16) & 0xff);
935  WriteU8 ((data >> 24) & 0xff);
936  WriteU8 ((data >> 32) & 0xff);
937  WriteU8 ((data >> 40) & 0xff);
938  WriteU8 ((data >> 48) & 0xff);
939  WriteU8 ((data >> 56) & 0xff);
940 }
941 
942 void
943 Buffer::Iterator::WriteHtonU64 (uint64_t data)
944 {
945  NS_LOG_FUNCTION (this << data);
946  WriteU8 ((data >> 56) & 0xff);
947  WriteU8 ((data >> 48) & 0xff);
948  WriteU8 ((data >> 40) & 0xff);
949  WriteU8 ((data >> 32) & 0xff);
950  WriteU8 ((data >> 24) & 0xff);
951  WriteU8 ((data >> 16) & 0xff);
952  WriteU8 ((data >> 8) & 0xff);
953  WriteU8 ((data >> 0) & 0xff);
954 }
955 void
956 Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
957 {
958  NS_LOG_FUNCTION (this << &buffer << size);
959  NS_ASSERT_MSG (CheckNoZero (m_current, size),
960  GetWriteErrorMessage ());
961  uint8_t *to;
962  if (m_current <= m_zeroStart)
963  {
964  to = &m_data[m_current];
965  }
966  else
967  {
968  to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
969  }
970  memcpy (to, buffer, size);
971  m_current += size;
972 }
973 
974 uint32_t
975 Buffer::Iterator::ReadU32 (void)
976 {
977  NS_LOG_FUNCTION (this);
978  uint8_t byte0 = ReadU8 ();
979  uint8_t byte1 = ReadU8 ();
980  uint8_t byte2 = ReadU8 ();
981  uint8_t byte3 = ReadU8 ();
982  uint32_t data = byte3;
983  data <<= 8;
984  data |= byte2;
985  data <<= 8;
986  data |= byte1;
987  data <<= 8;
988  data |= byte0;
989  return data;
990 }
991 uint64_t
992 Buffer::Iterator::ReadU64 (void)
993 {
994  NS_LOG_FUNCTION (this);
995  uint8_t byte0 = ReadU8 ();
996  uint8_t byte1 = ReadU8 ();
997  uint8_t byte2 = ReadU8 ();
998  uint8_t byte3 = ReadU8 ();
999  uint8_t byte4 = ReadU8 ();
1000  uint8_t byte5 = ReadU8 ();
1001  uint8_t byte6 = ReadU8 ();
1002  uint8_t byte7 = ReadU8 ();
1003  uint64_t data = byte7;
1004  data <<= 8;
1005  data |= byte6;
1006  data <<= 8;
1007  data |= byte5;
1008  data <<= 8;
1009  data |= byte4;
1010  data <<= 8;
1011  data |= byte3;
1012  data <<= 8;
1013  data |= byte2;
1014  data <<= 8;
1015  data |= byte1;
1016  data <<= 8;
1017  data |= byte0;
1018 
1019  return data;
1020 }
1021 uint16_t
1022 Buffer::Iterator::SlowReadNtohU16 (void)
1023 {
1024  NS_LOG_FUNCTION (this);
1025  uint16_t retval = 0;
1026  retval |= ReadU8 ();
1027  retval <<= 8;
1028  retval |= ReadU8 ();
1029  return retval;
1030 }
1031 uint32_t
1032 Buffer::Iterator::SlowReadNtohU32 (void)
1033 {
1034  NS_LOG_FUNCTION (this);
1035  uint32_t retval = 0;
1036  retval |= ReadU8 ();
1037  retval <<= 8;
1038  retval |= ReadU8 ();
1039  retval <<= 8;
1040  retval |= ReadU8 ();
1041  retval <<= 8;
1042  retval |= ReadU8 ();
1043  return retval;
1044 }
1045 uint64_t
1046 Buffer::Iterator::ReadNtohU64 (void)
1047 {
1048  NS_LOG_FUNCTION (this);
1049  uint64_t retval = 0;
1050  retval |= ReadU8 ();
1051  retval <<= 8;
1052  retval |= ReadU8 ();
1053  retval <<= 8;
1054  retval |= ReadU8 ();
1055  retval <<= 8;
1056  retval |= ReadU8 ();
1057  retval <<= 8;
1058  retval |= ReadU8 ();
1059  retval <<= 8;
1060  retval |= ReadU8 ();
1061  retval <<= 8;
1062  retval |= ReadU8 ();
1063  retval <<= 8;
1064  retval |= ReadU8 ();
1065  return retval;
1066 }
1067 uint16_t
1068 Buffer::Iterator::ReadLsbtohU16 (void)
1069 {
1070  NS_LOG_FUNCTION (this);
1071  uint8_t byte0 = ReadU8 ();
1072  uint8_t byte1 = ReadU8 ();
1073  uint16_t data = byte1;
1074  data <<= 8;
1075  data |= byte0;
1076  return data;
1077 }
1078 uint32_t
1079 Buffer::Iterator::ReadLsbtohU32 (void)
1080 {
1081  NS_LOG_FUNCTION (this);
1082  uint8_t byte0 = ReadU8 ();
1083  uint8_t byte1 = ReadU8 ();
1084  uint8_t byte2 = ReadU8 ();
1085  uint8_t byte3 = ReadU8 ();
1086  uint32_t data = byte3;
1087  data <<= 8;
1088  data |= byte2;
1089  data <<= 8;
1090  data |= byte1;
1091  data <<= 8;
1092  data |= byte0;
1093  return data;
1094 }
1095 uint64_t
1096 Buffer::Iterator::ReadLsbtohU64 (void)
1097 {
1098  NS_LOG_FUNCTION (this);
1099  uint8_t byte0 = ReadU8 ();
1100  uint8_t byte1 = ReadU8 ();
1101  uint8_t byte2 = ReadU8 ();
1102  uint8_t byte3 = ReadU8 ();
1103  uint8_t byte4 = ReadU8 ();
1104  uint8_t byte5 = ReadU8 ();
1105  uint8_t byte6 = ReadU8 ();
1106  uint8_t byte7 = ReadU8 ();
1107  uint64_t data = byte7;
1108  data <<= 8;
1109  data |= byte6;
1110  data <<= 8;
1111  data |= byte5;
1112  data <<= 8;
1113  data |= byte4;
1114  data <<= 8;
1115  data |= byte3;
1116  data <<= 8;
1117  data |= byte2;
1118  data <<= 8;
1119  data |= byte1;
1120  data <<= 8;
1121  data |= byte0;
1122 
1123  return data;
1124 }
1125 void
1126 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
1127 {
1128  NS_LOG_FUNCTION (this << &buffer << size);
1129  for (uint32_t i = 0; i < size; i++)
1130  {
1131  buffer[i] = ReadU8 ();
1132  }
1133 }
1134 
1135 uint16_t
1136 Buffer::Iterator::CalculateIpChecksum (uint16_t size)
1137 {
1138  NS_LOG_FUNCTION (this << size);
1139  return CalculateIpChecksum (size, 0);
1140 }
1141 
1142 uint16_t
1143 Buffer::Iterator::CalculateIpChecksum (uint16_t size, uint32_t initialChecksum)
1144 {
1145  NS_LOG_FUNCTION (this << size << initialChecksum);
1146  /* see RFC 1071 to understand this code. */
1147  uint32_t sum = initialChecksum;
1148 
1149  for (int j = 0; j < size/2; j++)
1150  sum += ReadU16 ();
1151 
1152  if (size & 1)
1153  sum += ReadU8 ();
1154 
1155  while (sum >> 16)
1156  sum = (sum & 0xffff) + (sum >> 16);
1157  return ~sum;
1158 }
1159 
1160 uint32_t
1162 {
1163  NS_LOG_FUNCTION (this);
1164  return m_dataEnd - m_dataStart;
1165 }
1166 
1167 uint32_t
1168 Buffer::Iterator::GetRemainingSize (void) const
1169 {
1170  NS_LOG_FUNCTION (this);
1171  return m_dataEnd - m_current;
1172 }
1173 
1174 
1175 std::string
1176 Buffer::Iterator::GetReadErrorMessage (void) const
1177 {
1178  NS_LOG_FUNCTION (this);
1179  std::string str = "You have attempted to read beyond the bounds of the "
1180  "available buffer space. This usually indicates that a "
1181  "Header::Deserialize or Trailer::Deserialize method "
1182  "is trying to read data which was not written by "
1183  "a Header::Serialize or Trailer::Serialize method. "
1184  "In short: check the code of your Serialize and Deserialize "
1185  "methods.";
1186  return str;
1187 }
1188 std::string
1189 Buffer::Iterator::GetWriteErrorMessage (void) const
1190 {
1191  NS_LOG_FUNCTION (this);
1192  std::string str;
1193  if (m_current < m_dataStart)
1194  {
1195  str = "You have attempted to write before the start of the available "
1196  "buffer space. This usually indicates that Trailer::GetSerializedSize "
1197  "returned a size which is too small compared to what Trailer::Serialize "
1198  "is actually using.";
1199  }
1200  else if (m_current >= m_dataEnd)
1201  {
1202  str = "You have attempted to write after the end of the available "
1203  "buffer space. This usually indicates that Header::GetSerializedSize "
1204  "returned a size which is too small compared to what Header::Serialize "
1205  "is actually using.";
1206  }
1207  else
1208  {
1209  NS_ASSERT (m_current >= m_zeroStart && m_current < m_zeroEnd);
1210  str = "You have attempted to write inside the payload area of the "
1211  "buffer. This usually indicates that your Serialize method uses more "
1212  "buffer space than what your GetSerialized method returned.";
1213  }
1214  return str;
1215 }
1216 
1217 
1218 } // namespace ns3
1219 
1220 
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
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:791
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:486
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition: buffer.h:484
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:441
#define min(a, b)
Definition: 80211b.c:42
uint32_t m_size
the size of the m_data field below.
Definition: buffer.h:670
automatically resized byte buffer
Definition: buffer.h:92
def start()
Definition: core.py:1806
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added...
Definition: wifi-utils.cc:163
uint32_t m_count
The reference count of an instance of this data structure.
Definition: buffer.h:666
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
bool CheckInternalState(void) const
Checks the internal buffer structures consistency.
Definition: buffer.cc:210
ns3::ByteTagListDataFreeList g_freeList
Container for struct ByteTagListData.
Local static destructor structure.
Definition: buffer.h:797
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:786
iterator in a Buffer instance
Definition: buffer.h:98
#define IS_INITIALIZED(x)
Definition: buffer.cc:75
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:459
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
uint8_t m_data[1]
The real data buffer holds at least one byte.
Definition: buffer.h:685
#define max(a, b)
Definition: 80211b.c:43
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition: buffer.h:660
void Prev(void)
go backward by one byte
Definition: buffer.h:851
static struct anonymous_namespace{buffer.cc}::Zeroes g_zeroes
Zero-filled buffer.
uint8_t data[writeSize]
Buffer::Iterator End(void) const
Definition: buffer.h:1075
#define DESTROYED
Definition: buffer.cc:76
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:479
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
#define IS_DESTROYED(x)
Definition: buffer.cc:74
void AddAtEnd(uint32_t end)
Definition: buffer.cc:354
std::vector< struct Buffer::Data * > FreeList
Container for buffer data.
Definition: buffer.h:795
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T > Create(void)
Create class instances by constructors with varying numbers of arguments and return them by Ptr...
Definition: ptr.h:516
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:474
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:464
uint32_t m_zeroAreaStart
offset to the start of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:776
uint32_t GetSize(void) const
Definition: buffer.h:1063
const uint32_t size
buffer size
Definition: buffer.cc:43
struct Data * m_data
the buffer data storage
Definition: buffer.h:752
char buffer[1000]
buffer containing zero values
Definition: buffer.cc:42
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:675
if(desigRtr==addrLocal)
void WriteU8(uint8_t data)
Definition: buffer.h:869
#define IS_UNINITIALIZED(x)
Definition: buffer.cc:73
uint32_t m_maxZeroAreaStart
keep track of the maximum value of m_zeroAreaStart across the lifetime of a Buffer instance...
Definition: buffer.h:764
Buffer CreateFullCopy(void) const
Create a full copy of the buffer, including all the internal structures.
Definition: buffer.cc:534
#define LOG_INTERNAL_STATE(y)
Definition: buffer.cc:24
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:956
static uint32_t g_maxSize
maximum data size (used for allocation)
uint32_t m_zeroAreaEnd
offset to the end of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:781