00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "tag-list.h"
00021 #include "ns3/log.h"
00022 #include <vector>
00023 #include <string.h>
00024
00025 NS_LOG_COMPONENT_DEFINE ("TagList");
00026
00027 #define USE_FREE_LIST 1
00028 #define FREE_LIST_SIZE 1000
00029 #define OFFSET_MAX (2147483647)
00030
00031 namespace ns3 {
00032
00033 struct TagListData {
00034 uint32_t size;
00035 uint32_t count;
00036 uint32_t dirty;
00037 uint8_t data[4];
00038 };
00039
00040 #ifdef USE_FREE_LIST
00041 static class TagListDataFreeList : public std::vector<struct TagListData *>
00042 {
00043 public:
00044 ~TagListDataFreeList ();
00045 } g_freeList;
00046 static uint32_t g_maxSize = 0;
00047
00048 TagListDataFreeList::~TagListDataFreeList ()
00049 {
00050 for (TagListDataFreeList::iterator i = begin ();
00051 i != end (); i++)
00052 {
00053 uint8_t *buffer = (uint8_t *)(*i);
00054 delete [] buffer;
00055 }
00056 }
00057 #endif
00058
00059 TagList::Iterator::Item::Item (TagBuffer buf_)
00060 : buf (buf_)
00061 {}
00062
00063 bool
00064 TagList::Iterator::HasNext (void) const
00065 {
00066 return m_current < m_end;
00067 }
00068 struct TagList::Iterator::Item
00069 TagList::Iterator::Next (void)
00070 {
00071 NS_ASSERT (HasNext ());
00072 struct Item item = Item (TagBuffer (m_current+16, m_end));
00073 item.tid.SetUid (m_nextTid);
00074 item.size = m_nextSize;
00075 item.start = std::max (m_nextStart, m_offsetStart);
00076 item.end = std::min (m_nextEnd, m_offsetEnd);
00077 m_current += 4 + 4 + 4 + 4 + item.size;
00078 item.buf.TrimAtEnd (m_end - m_current);
00079 PrepareForNext ();
00080 return item;
00081 }
00082 void
00083 TagList::Iterator::PrepareForNext (void)
00084 {
00085 while (m_current < m_end)
00086 {
00087 TagBuffer buf = TagBuffer (m_current, m_end);
00088 m_nextTid = buf.ReadU32 ();
00089 m_nextSize = buf.ReadU32 ();
00090 m_nextStart = buf.ReadU32 ();
00091 m_nextEnd = buf.ReadU32 ();
00092 if (m_nextStart >= m_offsetEnd || m_nextEnd <= m_offsetStart)
00093 {
00094 m_current += 4 + 4 + 4 + 4 + m_nextSize;
00095 }
00096 else
00097 {
00098 break;
00099 }
00100 }
00101 }
00102 TagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
00103 : m_current (start),
00104 m_end (end),
00105 m_offsetStart (offsetStart),
00106 m_offsetEnd (offsetEnd)
00107 {
00108 PrepareForNext ();
00109 }
00110
00111 uint32_t
00112 TagList::Iterator::GetOffsetStart (void) const
00113 {
00114 return m_offsetStart;
00115 }
00116
00117
00118 TagList::TagList ()
00119 : m_used (0),
00120 m_data (0)
00121 {
00122 NS_LOG_FUNCTION (this);
00123 }
00124 TagList::TagList (const TagList &o)
00125 : m_used (o.m_used),
00126 m_data (o.m_data)
00127 {
00128 NS_LOG_FUNCTION (this << &o);
00129 if (m_data != 0)
00130 {
00131 m_data->count++;
00132 }
00133 }
00134 TagList &
00135 TagList::operator = (const TagList &o)
00136 {
00137 NS_LOG_FUNCTION (this << &o);
00138 if (this == &o)
00139 {
00140 return *this;
00141 }
00142
00143 Deallocate (m_data);
00144 m_data = o.m_data;
00145 m_used = o.m_used;
00146 if (m_data != 0)
00147 {
00148 m_data->count++;
00149 }
00150 return *this;
00151 }
00152 TagList::~TagList ()
00153 {
00154 NS_LOG_FUNCTION (this);
00155 Deallocate (m_data);
00156 m_data = 0;
00157 m_used = 0;
00158 }
00159
00160 TagBuffer
00161 TagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
00162 {
00163 NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
00164 uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
00165 NS_ASSERT (m_used <= spaceNeeded);
00166 if (m_data == 0)
00167 {
00168 m_data = Allocate (spaceNeeded);
00169 m_used = 0;
00170 }
00171 else if (m_data->size < spaceNeeded ||
00172 (m_data->count != 1 && m_data->dirty != m_used))
00173 {
00174 struct TagListData *newData = Allocate (spaceNeeded);
00175 memcpy (&newData->data, &m_data->data, m_used);
00176 Deallocate (m_data);
00177 m_data = newData;
00178 }
00179 TagBuffer tag = TagBuffer (&m_data->data[m_used],
00180 &m_data->data[spaceNeeded]);
00181 tag.WriteU32 (tid.GetUid ());
00182 tag.WriteU32 (bufferSize);
00183 tag.WriteU32 (start);
00184 tag.WriteU32 (end);
00185 m_used = spaceNeeded;
00186 m_data->dirty = m_used;
00187 return tag;
00188 }
00189
00190 void
00191 TagList::Add (const TagList &o)
00192 {
00193 NS_LOG_FUNCTION (this << &o);
00194 TagList::Iterator i = o.BeginAll ();
00195 while (i.HasNext ())
00196 {
00197 TagList::Iterator::Item item = i.Next ();
00198 TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
00199 buf.CopyFrom (item.buf);
00200 }
00201 }
00202
00203 void
00204 TagList::RemoveAll (void)
00205 {
00206 NS_LOG_FUNCTION (this);
00207 Deallocate (m_data);
00208 m_data = 0;
00209 m_used = 0;
00210 }
00211
00212 TagList::Iterator
00213 TagList::BeginAll (void) const
00214 {
00215 NS_LOG_FUNCTION (this);
00216
00217
00218 return Begin (0, OFFSET_MAX);
00219 }
00220
00221 TagList::Iterator
00222 TagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
00223 {
00224 NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
00225 if (m_data == 0)
00226 {
00227 return Iterator (0, 0, offsetStart, offsetEnd);
00228 }
00229 else
00230 {
00231 return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
00232 }
00233 }
00234
00235 bool
00236 TagList::IsDirtyAtEnd (int32_t appendOffset)
00237 {
00238 NS_LOG_FUNCTION (this << appendOffset);
00239 TagList::Iterator i = BeginAll ();
00240 while (i.HasNext ())
00241 {
00242 TagList::Iterator::Item item = i.Next ();
00243 if (item.end > appendOffset)
00244 {
00245 return true;
00246 }
00247 }
00248 return false;
00249 }
00250
00251 bool
00252 TagList::IsDirtyAtStart (int32_t prependOffset)
00253 {
00254 NS_LOG_FUNCTION (this << prependOffset);
00255 TagList::Iterator i = BeginAll ();
00256 while (i.HasNext ())
00257 {
00258 TagList::Iterator::Item item = i.Next ();
00259 if (item.start < prependOffset)
00260 {
00261 return true;
00262 }
00263 }
00264 return false;
00265 }
00266
00267 void
00268 TagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
00269 {
00270 NS_LOG_FUNCTION (this << adjustment << appendOffset);
00271 if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
00272 {
00273 return;
00274 }
00275 TagList list;
00276 TagList::Iterator i = BeginAll ();
00277 while (i.HasNext ())
00278 {
00279 TagList::Iterator::Item item = i.Next ();
00280 item.start += adjustment;
00281 item.end += adjustment;
00282
00283 if (item.start >= appendOffset)
00284 {
00285 continue;
00286 }
00287 else if (item.start < appendOffset && item.end > appendOffset)
00288 {
00289 item.end = appendOffset;
00290 }
00291 else
00292 {
00293
00294 }
00295 TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
00296 buf.CopyFrom (item.buf);
00297 }
00298 *this = list;
00299 }
00300
00301 void
00302 TagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
00303 {
00304 NS_LOG_FUNCTION (this << adjustment << prependOffset);
00305 if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
00306 {
00307 return;
00308 }
00309 TagList list;
00310 TagList::Iterator i = BeginAll ();
00311 while (i.HasNext ())
00312 {
00313 TagList::Iterator::Item item = i.Next ();
00314 item.start += adjustment;
00315 item.end += adjustment;
00316
00317 if (item.end <= prependOffset)
00318 {
00319 continue;
00320 }
00321 else if (item.end > prependOffset && item.start < prependOffset)
00322 {
00323 item.start = prependOffset;
00324 }
00325 else
00326 {
00327
00328 }
00329 TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
00330 buf.CopyFrom (item.buf);
00331 }
00332 *this = list;
00333 }
00334
00335 #ifdef USE_FREE_LIST
00336
00337 struct TagListData *
00338 TagList::Allocate (uint32_t size)
00339 {
00340 NS_LOG_FUNCTION (this << size);
00341 while (!g_freeList.empty ())
00342 {
00343 struct TagListData *data = g_freeList.back ();
00344 g_freeList.pop_back ();
00345 NS_ASSERT (data != 0);
00346 if (data->size >= size)
00347 {
00348 data->count = 1;
00349 data->dirty = 0;
00350 return data;
00351 }
00352 uint8_t *buffer = (uint8_t *)data;
00353 delete [] buffer;
00354 }
00355 uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct TagListData) - 4];
00356 struct TagListData *data = (struct TagListData *)buffer;
00357 data->count = 1;
00358 data->size = size;
00359 data->dirty = 0;
00360 return data;
00361 }
00362
00363 void
00364 TagList::Deallocate (struct TagListData *data)
00365 {
00366 NS_LOG_FUNCTION (this << data);
00367 if (data == 0)
00368 {
00369 return;
00370 }
00371 g_maxSize = std::max (g_maxSize, data->size);
00372 data->count--;
00373 if (data->count == 0)
00374 {
00375 if (g_freeList.size () > FREE_LIST_SIZE ||
00376 data->size < g_maxSize)
00377 {
00378 uint8_t *buffer = (uint8_t *)data;
00379 delete [] buffer;
00380 }
00381 else
00382 {
00383 g_freeList.push_back (data);
00384 }
00385 }
00386 }
00387
00388 #else
00389
00390 struct TagListData *
00391 TagList::Allocate (uint32_t size)
00392 {
00393 NS_LOG_FUNCTION (this << size);
00394 uint8_t *buffer = new uint8_t [size + sizeof (struct TagListData) - 4];
00395 struct TagListData *data = (struct TagListData *)buffer;
00396 data->count = 1;
00397 data->size = size;
00398 data->dirty = 0;
00399 return data;
00400 }
00401
00402 void
00403 TagList::Deallocate (struct TagListData *data)
00404 {
00405 NS_LOG_FUNCTION (this << data);
00406 if (data == 0)
00407 {
00408 return;
00409 }
00410 data->count--;
00411 if (data->count == 0)
00412 {
00413 uint8_t *buffer = (uint8_t *)data;
00414 delete [] buffer;
00415 }
00416 }
00417
00418 #endif
00419
00420
00421 }