|
|
| 34 |
|
34 |
|
| 35 |
NS_LOG_COMPONENT_DEFINE ("PacketTagList"); |
35 |
NS_LOG_COMPONENT_DEFINE ("PacketTagList"); |
| 36 |
|
36 |
|
|
|
37 |
PacketTagList::TagData * |
| 38 |
PacketTagList::CreateTagData (size_t dataSize) |
| 39 |
{ |
| 40 |
NS_ASSERT_MSG (dataSize |
| 41 |
< std::numeric_limits<decltype(TagData::size)>::max (), |
| 42 |
"Requested TagData size " << dataSize |
| 43 |
<< " exceeds maximum " |
| 44 |
<< std::numeric_limits<decltype(TagData::size)>::max () ); |
| 45 |
|
| 46 |
void * p = std::malloc (sizeof (TagData) + dataSize - 1); |
| 47 |
// The matching frees are in RemoveAll and RemoveWriter |
| 48 |
|
| 49 |
TagData * tag = new (p) TagData; |
| 50 |
tag->size = dataSize; |
| 51 |
return tag; |
| 52 |
} |
| 53 |
|
| 37 |
bool |
54 |
bool |
| 38 |
PacketTagList::COWTraverse (Tag & tag, PacketTagList::COWWriter Writer) |
55 |
PacketTagList::COWTraverse (Tag & tag, PacketTagList::COWWriter Writer) |
| 39 |
{ |
56 |
{ |
|
|
| 133 |
NS_ASSERT (cur != 0); |
150 |
NS_ASSERT (cur != 0); |
| 134 |
NS_ASSERT (cur->count > 1); |
151 |
NS_ASSERT (cur->count > 1); |
| 135 |
cur->count--; // unmerge cur |
152 |
cur->count--; // unmerge cur |
| 136 |
struct TagData * copy = new struct TagData (); |
153 |
struct TagData * copy = CreateTagData (cur->size); |
| 137 |
copy->tid = cur->tid; |
154 |
copy->tid = cur->tid; |
| 138 |
copy->count = 1; |
155 |
copy->count = 1; |
| 139 |
memcpy (copy->data, cur->data, TagData::MAX_SIZE); |
156 |
copy->size = cur->size; |
|
|
157 |
memcpy (copy->data, cur->data, copy->size); |
| 140 |
copy->next = cur->next; // merge into tail |
158 |
copy->next = cur->next; // merge into tail |
| 141 |
copy->next->count++; // mark new merge |
159 |
copy->next->count++; // mark new merge |
| 142 |
*prevNext = copy; // point prior list at copy |
160 |
*prevNext = copy; // point prior list at copy |
|
|
| 170 |
|
188 |
|
| 171 |
// found tid |
189 |
// found tid |
| 172 |
bool found = true; |
190 |
bool found = true; |
| 173 |
tag.Deserialize (TagBuffer (cur->data, |
191 |
tag.Deserialize (TagBuffer (cur->data, cur->data + cur->size)); |
| 174 |
cur->data + TagData::MAX_SIZE)); |
|
|
| 175 |
*prevNext = cur->next; // link around cur |
192 |
*prevNext = cur->next; // link around cur |
| 176 |
|
193 |
|
| 177 |
if (preMerge) |
194 |
if (preMerge) |
| 178 |
{ |
195 |
{ |
| 179 |
// found tid before first merge, so delete cur |
196 |
// found tid before first merge, so delete cur |
| 180 |
delete cur; |
197 |
cur->~TagData (); |
|
|
198 |
std::free (cur); |
| 181 |
} |
199 |
} |
| 182 |
else |
200 |
else |
| 183 |
{ |
201 |
{ |
|
|
| 217 |
if (preMerge) |
235 |
if (preMerge) |
| 218 |
{ |
236 |
{ |
| 219 |
// found tid before first merge, so just rewrite |
237 |
// found tid before first merge, so just rewrite |
| 220 |
tag.Serialize (TagBuffer (cur->data, |
238 |
tag.Serialize (TagBuffer (cur->data, cur->data + cur->size)); |
| 221 |
cur->data + tag.GetSerializedSize ())); |
|
|
| 222 |
} |
239 |
} |
| 223 |
else |
240 |
else |
| 224 |
{ |
241 |
{ |
| 225 |
// cur is always a merge at this point |
242 |
// cur is always a merge at this point |
| 226 |
// need to copy, replace, and link past cur |
243 |
// need to copy, replace, and link past cur |
| 227 |
cur->count--; // unmerge cur |
244 |
cur->count--; // unmerge cur |
| 228 |
struct TagData * copy = new struct TagData (); |
245 |
struct TagData * copy = CreateTagData (tag.GetSerializedSize ()); |
| 229 |
copy->tid = tag.GetInstanceTypeId (); |
246 |
copy->tid = tag.GetInstanceTypeId (); |
| 230 |
copy->count = 1; |
247 |
copy->count = 1; |
| 231 |
tag.Serialize (TagBuffer (copy->data, |
248 |
tag.Serialize (TagBuffer (copy->data, copy->data + copy->size)); |
| 232 |
copy->data + tag.GetSerializedSize ())); |
|
|
| 233 |
copy->next = cur->next; // merge into tail |
249 |
copy->next = cur->next; // merge into tail |
| 234 |
if (copy->next != 0) |
250 |
if (copy->next != 0) |
| 235 |
{ |
251 |
{ |
|
|
| 247 |
// ensure this id was not yet added |
263 |
// ensure this id was not yet added |
| 248 |
for (struct TagData *cur = m_next; cur != 0; cur = cur->next) |
264 |
for (struct TagData *cur = m_next; cur != 0; cur = cur->next) |
| 249 |
{ |
265 |
{ |
| 250 |
NS_ASSERT_MSG (cur->tid != tag.GetInstanceTypeId (), "Error: cannot add the same kind of tag twice."); |
266 |
NS_ASSERT_MSG (cur->tid != tag.GetInstanceTypeId (), |
|
|
267 |
"Error: cannot add the same kind of tag twice."); |
| 251 |
} |
268 |
} |
| 252 |
struct TagData * head = new struct TagData (); |
269 |
struct TagData * head = CreateTagData (tag.GetSerializedSize ()); |
| 253 |
head->count = 1; |
270 |
head->count = 1; |
| 254 |
head->next = 0; |
271 |
head->next = 0; |
| 255 |
head->tid = tag.GetInstanceTypeId (); |
272 |
head->tid = tag.GetInstanceTypeId (); |
| 256 |
head->next = m_next; |
273 |
head->next = m_next; |
| 257 |
NS_ASSERT (tag.GetSerializedSize () <= TagData::MAX_SIZE); |
274 |
tag.Serialize (TagBuffer (head->data, head->data + head->size)); |
| 258 |
tag.Serialize (TagBuffer (head->data, head->data + tag.GetSerializedSize ())); |
|
|
| 259 |
|
275 |
|
| 260 |
const_cast<PacketTagList *> (this)->m_next = head; |
276 |
const_cast<PacketTagList *> (this)->m_next = head; |
| 261 |
} |
277 |
} |
|
|
| 270 |
if (cur->tid == tid) |
286 |
if (cur->tid == tid) |
| 271 |
{ |
287 |
{ |
| 272 |
/* found tag */ |
288 |
/* found tag */ |
| 273 |
tag.Deserialize (TagBuffer (cur->data, cur->data + TagData::MAX_SIZE)); |
289 |
tag.Deserialize (TagBuffer (cur->data, cur->data + cur->size)); |
| 274 |
return true; |
290 |
return true; |
| 275 |
} |
291 |
} |
| 276 |
} |
292 |
} |