A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
byte-tag-list.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 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 "byte-tag-list.h"
21 #include "ns3/log.h"
22 #include <vector>
23 #include <cstring>
24 
25 NS_LOG_COMPONENT_DEFINE ("ByteTagList");
26 
27 #define USE_FREE_LIST 1
28 #define FREE_LIST_SIZE 1000
29 #define OFFSET_MAX (2147483647)
30 
31 namespace ns3 {
32 
41  uint32_t size;
42  uint32_t count;
43  uint32_t dirty;
44  uint8_t data[4];
45 };
46 
47 #ifdef USE_FREE_LIST
48 
55 static class ByteTagListDataFreeList : public std::vector<struct ByteTagListData *>
56 {
57 public:
59 } g_freeList;
60 static uint32_t g_maxSize = 0;
61 
63 {
64  NS_LOG_FUNCTION (this);
65  for (ByteTagListDataFreeList::iterator i = begin ();
66  i != end (); i++)
67  {
68  uint8_t *buffer = (uint8_t *)(*i);
69  delete [] buffer;
70  }
71 }
72 #endif /* USE_FREE_LIST */
73 
75  : buf (buf_)
76 {
77  NS_LOG_FUNCTION (this << &buf_);
78 }
79 
80 bool
82 {
83  NS_LOG_FUNCTION (this);
84  return m_current < m_end;
85 }
88 {
89  NS_ASSERT (HasNext ());
90  struct Item item = Item (TagBuffer (m_current+16, m_end));
91  item.tid.SetUid (m_nextTid);
92  item.size = m_nextSize;
93  item.start = std::max (m_nextStart, m_offsetStart);
94  item.end = std::min (m_nextEnd, m_offsetEnd);
95  m_current += 4 + 4 + 4 + 4 + item.size;
96  item.buf.TrimAtEnd (m_end - m_current);
97  PrepareForNext ();
98  return item;
99 }
100 void
102 {
103  NS_LOG_FUNCTION (this);
104  while (m_current < m_end)
105  {
107  m_nextTid = buf.ReadU32 ();
108  m_nextSize = buf.ReadU32 ();
109  m_nextStart = buf.ReadU32 ();
110  m_nextEnd = buf.ReadU32 ();
112  {
113  m_current += 4 + 4 + 4 + 4 + m_nextSize;
114  }
115  else
116  {
117  break;
118  }
119  }
120 }
121 ByteTagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
122  : m_current (start),
123  m_end (end),
124  m_offsetStart (offsetStart),
125  m_offsetEnd (offsetEnd)
126 {
127  NS_LOG_FUNCTION (this << &start << &end << offsetStart << offsetEnd);
128  PrepareForNext ();
129 }
130 
131 uint32_t
133 {
134  NS_LOG_FUNCTION (this);
135  return m_offsetStart;
136 }
137 
138 
140  : m_used (0),
141  m_data (0)
142 {
143  NS_LOG_FUNCTION (this);
144 }
146  : m_used (o.m_used),
147  m_data (o.m_data)
148 {
149  NS_LOG_FUNCTION (this << &o);
150  if (m_data != 0)
151  {
152  m_data->count++;
153  }
154 }
155 ByteTagList &
157 {
158  if (this == &o)
159  {
160  return *this;
161  }
162 
163  Deallocate (m_data);
164  m_data = o.m_data;
165  m_used = o.m_used;
166  if (m_data != 0)
167  {
168  m_data->count++;
169  }
170  return *this;
171 }
173 {
174  NS_LOG_FUNCTION (this);
175  Deallocate (m_data);
176  m_data = 0;
177  m_used = 0;
178 }
179 
180 TagBuffer
181 ByteTagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
182 {
183  NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
184  uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
185  NS_ASSERT (m_used <= spaceNeeded);
186  if (m_data == 0)
187  {
188  m_data = Allocate (spaceNeeded);
189  m_used = 0;
190  }
191  else if (m_data->size < spaceNeeded ||
192  (m_data->count != 1 && m_data->dirty != m_used))
193  {
194  struct ByteTagListData *newData = Allocate (spaceNeeded);
195  std::memcpy (&newData->data, &m_data->data, m_used);
196  Deallocate (m_data);
197  m_data = newData;
198  }
199  TagBuffer tag = TagBuffer (&m_data->data[m_used],
200  &m_data->data[spaceNeeded]);
201  tag.WriteU32 (tid.GetUid ());
202  tag.WriteU32 (bufferSize);
203  tag.WriteU32 (start);
204  tag.WriteU32 (end);
205  m_used = spaceNeeded;
206  m_data->dirty = m_used;
207  return tag;
208 }
209 
210 void
212 {
213  NS_LOG_FUNCTION (this << &o);
215  while (i.HasNext ())
216  {
217  ByteTagList::Iterator::Item item = i.Next ();
218  TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
219  buf.CopyFrom (item.buf);
220  }
221 }
222 
223 void
225 {
226  NS_LOG_FUNCTION (this);
227  Deallocate (m_data);
228  m_data = 0;
229  m_used = 0;
230 }
231 
234 {
235  NS_LOG_FUNCTION (this);
236  // I am not totally sure but I might need to use
237  // INT32_MIN instead of zero below.
238  return Begin (0, OFFSET_MAX);
239 }
240 
242 ByteTagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
243 {
244  NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
245  if (m_data == 0)
246  {
247  return Iterator (0, 0, offsetStart, offsetEnd);
248  }
249  else
250  {
251  return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
252  }
253 }
254 
255 bool
256 ByteTagList::IsDirtyAtEnd (int32_t appendOffset)
257 {
258  NS_LOG_FUNCTION (this << appendOffset);
260  while (i.HasNext ())
261  {
262  ByteTagList::Iterator::Item item = i.Next ();
263  if (item.end > appendOffset)
264  {
265  return true;
266  }
267  }
268  return false;
269 }
270 
271 bool
272 ByteTagList::IsDirtyAtStart (int32_t prependOffset)
273 {
274  NS_LOG_FUNCTION (this << prependOffset);
276  while (i.HasNext ())
277  {
278  ByteTagList::Iterator::Item item = i.Next ();
279  if (item.start < prependOffset)
280  {
281  return true;
282  }
283  }
284  return false;
285 }
286 
287 void
288 ByteTagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
289 {
290  NS_LOG_FUNCTION (this << adjustment << appendOffset);
291  if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
292  {
293  return;
294  }
297  while (i.HasNext ())
298  {
299  ByteTagList::Iterator::Item item = i.Next ();
300  item.start += adjustment;
301  item.end += adjustment;
302 
303  if (item.start >= appendOffset)
304  {
305  continue;
306  }
307  else if (item.start < appendOffset && item.end > appendOffset)
308  {
309  item.end = appendOffset;
310  }
311  else
312  {
313  // nothing to do.
314  }
315  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
316  buf.CopyFrom (item.buf);
317  }
318  *this = list;
319 }
320 
321 void
322 ByteTagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
323 {
324  NS_LOG_FUNCTION (this << adjustment << prependOffset);
325  if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
326  {
327  return;
328  }
331  while (i.HasNext ())
332  {
333  ByteTagList::Iterator::Item item = i.Next ();
334  item.start += adjustment;
335  item.end += adjustment;
336 
337  if (item.end <= prependOffset)
338  {
339  continue;
340  }
341  else if (item.end > prependOffset && item.start < prependOffset)
342  {
343  item.start = prependOffset;
344  }
345  else
346  {
347  // nothing to do.
348  }
349  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
350  buf.CopyFrom (item.buf);
351  }
352  *this = list;
353 }
354 
355 #ifdef USE_FREE_LIST
356 
357 struct ByteTagListData *
358 ByteTagList::Allocate (uint32_t size)
359 {
360  NS_LOG_FUNCTION (this << size);
361  while (!g_freeList.empty ())
362  {
363  struct ByteTagListData *data = g_freeList.back ();
364  g_freeList.pop_back ();
365  NS_ASSERT (data != 0);
366  if (data->size >= size)
367  {
368  data->count = 1;
369  data->dirty = 0;
370  return data;
371  }
372  uint8_t *buffer = (uint8_t *)data;
373  delete [] buffer;
374  }
375  uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct ByteTagListData) - 4];
376  struct ByteTagListData *data = (struct ByteTagListData *)buffer;
377  data->count = 1;
378  data->size = size;
379  data->dirty = 0;
380  return data;
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION (this << data);
387  if (data == 0)
388  {
389  return;
390  }
391  g_maxSize = std::max (g_maxSize, data->size);
392  data->count--;
393  if (data->count == 0)
394  {
395  if (g_freeList.size () > FREE_LIST_SIZE ||
396  data->size < g_maxSize)
397  {
398  uint8_t *buffer = (uint8_t *)data;
399  delete [] buffer;
400  }
401  else
402  {
403  g_freeList.push_back (data);
404  }
405  }
406 }
407 
408 #else /* USE_FREE_LIST */
409 
410 struct ByteTagListData *
411 ByteTagList::Allocate (uint32_t size)
412 {
413  NS_LOG_FUNCTION (this << size);
414  uint8_t *buffer = new uint8_t [size + sizeof (struct ByteTagListData) - 4];
415  struct ByteTagListData *data = (struct ByteTagListData *)buffer;
416  data->count = 1;
417  data->size = size;
418  data->dirty = 0;
419  return data;
420 }
421 
422 void
423 ByteTagList::Deallocate (struct ByteTagListData *data)
424 {
425  NS_LOG_FUNCTION (this << data);
426  if (data == 0)
427  {
428  return;
429  }
430  data->count--;
431  if (data->count == 0)
432  {
433  uint8_t *buffer = (uint8_t *)data;
434  delete [] buffer;
435  }
436 }
437 
438 #endif /* USE_FREE_LIST */
439 
440 
441 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t dirty
number of bytes actually in use
ByteTagList & operator=(const ByteTagList &o)
Assignment operator, deallocates current data and assigns value of passed in ByteTagList.
Iterator(uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
Constructor.
struct ByteTagListData * m_data
the ByteTagListData structure
uint32_t count
use counter (for smart deallocation)
keep track of the byte tags stored in a packet.
Definition: byte-tag-list.h:68
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
bool HasNext(void) const
Used to determine if the iterator is at the end of the byteTagList.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
TagBuffer Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
void TrimAtEnd(uint32_t trim)
Trim some space from the end.
Definition: tag-buffer.cc:192
uint32_t m_nextTid
TypeId of the next tag.
TAG_BUFFER_INLINE uint32_t ReadU32(void)
Definition: tag-buffer.h:215
ns3::ByteTagListDataFreeList g_freeList
Container for struct ByteTagListData.
void Deallocate(struct ByteTagListData *data)
Deallocates a ByteTagListData.
uint8_t * m_current
Current tag.
#define FREE_LIST_SIZE
int32_t m_offsetEnd
Offset to the end of the tag from the virtual byte buffer.
void PrepareForNext(void)
Prepare the iterator for the next tag.
void RemoveAll(void)
Removes all of the tags from the ByteTagList.
Internal representation of the byte tags stored in a packet.
uint32_t m_nextSize
Size of the next tag.
uint8_t data[writeSize]
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:186
#define OFFSET_MAX
uint16_t m_used
the number of used bytes in the buffer
int32_t start
offset to the start of the tag from the virtual byte buffer
Definition: byte-tag-list.h:90
void AddAtEnd(int32_t adjustment, int32_t appendOffset)
Adjust the offsets stored internally by the adjustment delta and make sure that all offsets are small...
struct ByteTagList::Iterator::Item Next(void)
Returns the next Item from the ByteTagList.
#define list
struct ByteTagListData * Allocate(uint32_t size)
Allocate the memory for the ByteTagListData.
void SetUid(uint16_t tid)
Definition: type-id.cc:818
int32_t m_nextStart
Start of the next tag.
uint32_t GetOffsetStart(void) const
Returns the offset from the start of the virtual byte buffer to the ByteTagList.
int32_t end
offset to the end of the tag from the virtual byte buffer
Definition: byte-tag-list.h:91
uint16_t GetUid(void) const
Definition: type-id.cc:812
ByteTagList::Iterator BeginAll(void) const
Returns an iterator pointing to the very first tag in this list.
int32_t m_offsetStart
Offset to the start of the tag from the virtual byte buffer.
Container class for struct ByteTagListData.
TypeId tid
type of the tag
Definition: byte-tag-list.h:88
uint32_t size
size of tag data
Definition: byte-tag-list.h:89
uint32_t size
size of the data
bool IsDirtyAtStart(int32_t prependOffset)
Check that all offsets are bigger than prependOffset.
ByteTagList::Iterator Begin(int32_t offsetStart, int32_t offsetEnd) const
TagBuffer buf
the data for the tag as generated by Tag::Serialize
Definition: byte-tag-list.h:92
An iterator for iterating through a byte tag list.
Definition: byte-tag-list.h:77
read and write tag data
Definition: tag-buffer.h:51
int32_t m_nextEnd
End of the next tag.
Item(TagBuffer buf)
constructs an item with the given TagBuffer
bool IsDirtyAtEnd(int32_t appendOffset)
Check that all offsets are smaller than appendOffset.
uint8_t data[4]
data
static uint32_t g_maxSize
maximum data size (used for allocation)
a unique identifier for an interface.
Definition: type-id.h:49
void CopyFrom(TagBuffer o)
Copy the nternal structure of another TagBuffer.
Definition: tag-buffer.cc:200
void AddAtStart(int32_t adjustment, int32_t prependOffset)
Adjust the offsets stored internally by the adjustment delta and make sure that all offsets are bigge...
uint8_t * m_end
End tag.
An item specifies an individual tag within a byte buffer.
Definition: byte-tag-list.h:86