LEFT | RIGHT |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2005,2006,2007 INRIA | 3 * Copyright (c) 2005,2006,2007 INRIA |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 2 as |
7 * published by the Free Software Foundation; | 7 * published by the Free Software Foundation; |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 20 matching lines...) Expand all Loading... |
31 #define LOG_INTERNAL_STATE(y)
\ | 31 #define LOG_INTERNAL_STATE(y)
\ |
32 NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAr
eaStart<< \ | 32 NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAr
eaStart<< \ |
33 ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<
m_data->m_size<< \ | 33 ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<
m_data->m_size<< \ |
34 ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirt
yEnd) | 34 ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirt
yEnd) |
35 | 35 |
36 #ifdef BUFFER_HEURISTICS | 36 #ifdef BUFFER_HEURISTICS |
37 #define HEURISTICS(x) x | 37 #define HEURISTICS(x) x |
38 #else | 38 #else |
39 #define HEURISTICS(x) | 39 #define HEURISTICS(x) |
40 #endif | 40 #endif |
| 41 |
| 42 namespace { |
| 43 |
| 44 static struct Zeroes |
| 45 { |
| 46 Zeroes () |
| 47 : size (1000) |
| 48 { |
| 49 memset (buffer, 0, size); |
| 50 } |
| 51 char buffer[1000]; |
| 52 const uint32_t size; |
| 53 } g_zeroes; |
| 54 |
| 55 } |
41 | 56 |
42 //#define PRINT_STATS 1 | 57 //#define PRINT_STATS 1 |
43 | 58 |
44 namespace ns3 { | 59 namespace ns3 { |
45 | 60 |
46 /** | 61 /** |
47 * This data structure is variable-sized through its last member whose size | 62 * This data structure is variable-sized through its last member whose size |
48 * is determined at allocation time and stored in the m_size field. | 63 * is determined at allocation time and stored in the m_size field. |
49 * | 64 * |
50 * The so-called "dirty area" describes the area in the buffer which | 65 * The so-called "dirty area" describes the area in the buffer which |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 NS_LOG_FUNCTION (this); | 261 NS_LOG_FUNCTION (this); |
247 Initialize (0); | 262 Initialize (0); |
248 } | 263 } |
249 | 264 |
250 Buffer::Buffer (uint32_t dataSize) | 265 Buffer::Buffer (uint32_t dataSize) |
251 { | 266 { |
252 NS_LOG_FUNCTION (this << dataSize); | 267 NS_LOG_FUNCTION (this << dataSize); |
253 Initialize (dataSize); | 268 Initialize (dataSize); |
254 } | 269 } |
255 | 270 |
| 271 Buffer::Buffer (uint32_t dataSize, bool initialize) |
| 272 { |
| 273 NS_LOG_FUNCTION (this << dataSize << initialize); |
| 274 if (initialize == true) |
| 275 { |
| 276 Initialize (dataSize); |
| 277 } |
| 278 } |
| 279 |
256 bool | 280 bool |
257 Buffer::CheckInternalState (void) const | 281 Buffer::CheckInternalState (void) const |
258 { | 282 { |
259 bool offsetsOk =· | 283 bool offsetsOk =· |
260 m_start <= m_zeroAreaStart && | 284 m_start <= m_zeroAreaStart && |
261 m_zeroAreaStart <= m_zeroAreaEnd && | 285 m_zeroAreaStart <= m_zeroAreaEnd && |
262 m_zeroAreaEnd <= m_end; | 286 m_zeroAreaEnd <= m_end; |
263 bool dirtyOk = | 287 bool dirtyOk = |
264 m_start >= m_data->m_dirtyStart && | 288 m_start >= m_data->m_dirtyStart && |
265 m_end <= m_data->m_dirtyEnd; | 289 m_end <= m_data->m_dirtyEnd; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 Buffer::Iterator i = tmp.End (); | 669 Buffer::Iterator i = tmp.End (); |
646 i.Prev (dataEnd); | 670 i.Prev (dataEnd); |
647 i.Write (m_data->m_data+m_zeroAreaStart,dataEnd); | 671 i.Write (m_data->m_data+m_zeroAreaStart,dataEnd); |
648 NS_ASSERT (tmp.CheckInternalState ()); | 672 NS_ASSERT (tmp.CheckInternalState ()); |
649 return tmp; | 673 return tmp; |
650 } | 674 } |
651 NS_ASSERT (CheckInternalState ()); | 675 NS_ASSERT (CheckInternalState ()); |
652 return *this; | 676 return *this; |
653 } | 677 } |
654 | 678 |
655 Buffer· | 679 uint32_t· |
656 Buffer::CreateCompressedCopy (void) const | 680 Buffer::GetSerializedSize (void) const |
657 { | 681 { |
| 682 uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3); |
| 683 uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3); |
| 684 |
| 685 // total size 4-bytes for dataStart length· |
| 686 // + X number of bytes for dataStart· |
| 687 // + 4-bytes for dataEnd length· |
| 688 // + X number of bytes for dataEnd |
| 689 uint32_t sz = sizeof (uint32_t) |
| 690 + sizeof (uint32_t) |
| 691 + dataStart |
| 692 + sizeof (uint32_t) |
| 693 + dataEnd; |
| 694 |
| 695 return sz; |
| 696 } |
| 697 |
| 698 uint32_t |
| 699 Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const |
| 700 { |
| 701 uint32_t* p = (uint32_t*)buffer; |
| 702 uint32_t size = 0; |
| 703 ·· |
658 NS_LOG_FUNCTION (this); | 704 NS_LOG_FUNCTION (this); |
659 NS_ASSERT (CheckInternalState ()); | 705 |
660 | 706 // Add the zero data length |
661 Buffer tmpBuffer; | 707 if (size + 4 <= maxSize) |
662 uint32_t dataEnd = m_end - m_zeroAreaEnd; | 708 { |
663 tmpBuffer.AddAtStart (dataEnd); | 709 size += 4; |
664 tmpBuffer.Begin ().Write (m_data->m_data+m_zeroAreaStart,dataEnd); | 710 *p++ = m_zeroAreaEnd - m_zeroAreaStart; |
665 tmpBuffer.AddAtStart (4); | 711 } |
666 tmpBuffer.Begin ().WriteU32 (dataEnd); | 712 else |
667 | 713 { |
668 uint32_t dataStart = m_zeroAreaStart - m_start; | 714 return 0; |
669 tmpBuffer.AddAtStart (dataStart); | 715 } |
670 tmpBuffer.Begin ().Write (m_data->m_data+m_start, dataStart); | 716 |
671 tmpBuffer.AddAtStart (4); | 717 // Add the length of actual start data |
672 tmpBuffer.Begin ().WriteU32 (dataStart); | 718 uint32_t dataStartLength = m_zeroAreaStart - m_start; |
673 | 719 if (size + 4 <= maxSize) |
674 tmpBuffer.AddAtStart (4); | 720 { |
675 tmpBuffer.Begin ().WriteU32 (m_zeroAreaEnd - m_zeroAreaStart); | 721 size += 4; |
676 | 722 *p++ = dataStartLength; |
677 NS_ASSERT (tmpBuffer.CheckInternalState ()); | 723 } |
678 | 724 else |
679 return tmpBuffer; | 725 { |
| 726 return 0; |
| 727 } |
| 728 |
| 729 // Add the actual data |
| 730 if (size + ((dataStartLength + 3) & (~3)) <= maxSize) |
| 731 { |
| 732 size += (dataStartLength + 3) & (~3); |
| 733 memcpy(p, m_data->m_data + m_start, dataStartLength); |
| 734 p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte bou
ndary |
| 735 } |
| 736 else |
| 737 { |
| 738 return 0; |
| 739 } |
| 740 |
| 741 // Add the length of the actual end data |
| 742 uint32_t dataEndLength = m_end - m_zeroAreaEnd; |
| 743 if (size + 4 <= maxSize) |
| 744 { |
| 745 size += 4; |
| 746 *p++ = dataEndLength; |
| 747 } |
| 748 else |
| 749 { |
| 750 return 0; |
| 751 } |
| 752 |
| 753 // Add the actual data |
| 754 if (size + ((dataEndLength + 3) & (~3)) <= maxSize) |
| 755 { |
| 756 size += (dataEndLength + 3) & (~3); |
| 757 memcpy(p, m_data->m_data+m_zeroAreaStart,dataEndLength); |
| 758 p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte bound
ary |
| 759 } |
| 760 else |
| 761 { |
| 762 return 0; |
| 763 } |
| 764 |
| 765 // Serialzed everything successfully |
| 766 return 1; |
| 767 } |
| 768 |
| 769 uint32_t· |
| 770 Buffer::Deserialize (uint8_t *buffer, uint32_t size) |
| 771 { |
| 772 uint32_t* p = (uint32_t*)buffer; |
| 773 uint32_t sizeCheck = size-4; |
| 774 |
| 775 NS_ASSERT (sizeCheck >= 4); |
| 776 uint32_t zeroDataLength = *p++; |
| 777 sizeCheck -= 4; |
| 778 |
| 779 // Create zero bytes |
| 780 Initialize (zeroDataLength); |
| 781 ·· |
| 782 // Add start data |
| 783 NS_ASSERT (sizeCheck >= 4); |
| 784 uint32_t dataStartLength = *p++; |
| 785 sizeCheck -= 4; |
| 786 AddAtStart (dataStartLength); |
| 787 |
| 788 NS_ASSERT (sizeCheck >= dataStartLength); |
| 789 Begin ().Write ((uint8_t*)p, dataStartLength); |
| 790 p += (((dataStartLength+3)&(~3))/4); |
| 791 sizeCheck -= ((dataStartLength+3)&(~3)); |
| 792 |
| 793 // Add end data |
| 794 NS_ASSERT (sizeCheck >= 4); |
| 795 uint32_t dataEndLength = *p++; |
| 796 sizeCheck -= 4; |
| 797 AddAtEnd (dataEndLength); |
| 798 |
| 799 NS_ASSERT (sizeCheck >= dataEndLength); |
| 800 Buffer::Iterator tmp = End (); |
| 801 tmp.Prev (dataEndLength); |
| 802 tmp.Write ((uint8_t*)p, dataEndLength); |
| 803 p += (((dataEndLength+3)&(~3))/4); |
| 804 sizeCheck -= ((dataEndLength+3)&(~3)); |
| 805 ·· |
| 806 NS_ASSERT (sizeCheck == 0); |
| 807 // return zero if buffer did not· |
| 808 // contain a complete message |
| 809 return (sizeCheck != 0) ? 0 : 1; |
680 } | 810 } |
681 | 811 |
682 int32_t· | 812 int32_t· |
683 Buffer::GetCurrentStartOffset (void) const | 813 Buffer::GetCurrentStartOffset (void) const |
684 { | 814 { |
685 return m_start; | 815 return m_start; |
686 } | 816 } |
687 int32_t· | 817 int32_t· |
688 Buffer::GetCurrentEndOffset (void) const | 818 Buffer::GetCurrentEndOffset (void) const |
689 { | 819 { |
(...skipping 24 matching lines...) Expand all Loading... |
714 Buffer::CopyData(std::ostream *os, uint32_t size) const | 844 Buffer::CopyData(std::ostream *os, uint32_t size) const |
715 { | 845 { |
716 if (size > 0) | 846 if (size > 0) |
717 { | 847 { |
718 uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size); | 848 uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size); |
719 os->write((const char*)(m_data->m_data + m_start), tmpsize); | 849 os->write((const char*)(m_data->m_data + m_start), tmpsize); |
720 if (size > tmpsize)· | 850 if (size > tmpsize)· |
721 {· | 851 {· |
722 size -= m_zeroAreaStart-m_start; | 852 size -= m_zeroAreaStart-m_start; |
723 tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size); | 853 tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size); |
724 char zero = 0; | 854 uint32_t left = tmpsize; |
725 for (uint32_t i = 0; i < tmpsize; ++i) | 855 while (left > 0) |
726 { | 856 { |
727 os->write (&zero, 1); | 857 uint32_t toWrite = std::min (left, g_zeroes.size); |
| 858 os->write (g_zeroes.buffer, toWrite); |
| 859 left -= toWrite; |
728 } | 860 } |
729 if (size > tmpsize) | 861 if (size > tmpsize) |
730 { | 862 { |
731 size -= tmpsize; | 863 size -= tmpsize; |
732 tmpsize = std::min (m_end - m_zeroAreaEnd, size); | 864 tmpsize = std::min (m_end - m_zeroAreaEnd, size); |
733 os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsiz
e);· | 865 os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsiz
e);· |
734 } | 866 } |
735 } | 867 } |
736 } | 868 } |
| 869 } |
| 870 |
| 871 uint32_t· |
| 872 Buffer::CopyData (uint8_t *buffer, uint32_t size) const |
| 873 { |
| 874 uint32_t originalSize = size; |
| 875 if (size > 0) |
| 876 { |
| 877 uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size); |
| 878 memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize); |
| 879 buffer += tmpsize; |
| 880 if (size > tmpsize)· |
| 881 {· |
| 882 size -= m_zeroAreaStart-m_start; |
| 883 tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size); |
| 884 uint32_t left = tmpsize; |
| 885 while (left > 0) |
| 886 { |
| 887 uint32_t toWrite = std::min (left, g_zeroes.size); |
| 888 memcpy (buffer, g_zeroes.buffer, toWrite); |
| 889 left -= toWrite; |
| 890 buffer += toWrite; |
| 891 } |
| 892 if (size > tmpsize) |
| 893 { |
| 894 size -= tmpsize; |
| 895 tmpsize = std::min (m_end - m_zeroAreaEnd, size); |
| 896 memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), t
mpsize); |
| 897 } |
| 898 } |
| 899 } |
| 900 return originalSize - size; |
737 } | 901 } |
738 | 902 |
739 /****************************************************** | 903 /****************************************************** |
740 * The buffer iterator below. | 904 * The buffer iterator below. |
741 ******************************************************/ | 905 ******************************************************/ |
742 | 906 |
743 | 907 |
744 Buffer::Iterator::Iterator () | 908 Buffer::Iterator::Iterator () |
745 : m_zeroStart (0), | 909 : m_zeroStart (0), |
746 m_zeroEnd (0), | 910 m_zeroEnd (0), |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 return data; | 1277 return data; |
1114 } | 1278 } |
1115 void· | 1279 void· |
1116 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size) | 1280 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size) |
1117 { | 1281 { |
1118 for (uint32_t i = 0; i < size; i++) | 1282 for (uint32_t i = 0; i < size; i++) |
1119 { | 1283 { |
1120 buffer[i] = ReadU8 (); | 1284 buffer[i] = ReadU8 (); |
1121 } | 1285 } |
1122 } | 1286 } |
1123 | |
1124 #ifndef BUFFER_USE_INLINE | |
1125 | |
1126 void· | |
1127 Buffer::Iterator::WriteU8 (uint8_t data) | |
1128 { | |
1129 if (m_current < m_dataStart) | |
1130 { | |
1131 // XXX trying to write outside of data area | |
1132 NS_ASSERT (false); | |
1133 } | |
1134 else if (m_current < m_zeroStart) | |
1135 { | |
1136 m_data[m_current] = data; | |
1137 m_current++; | |
1138 } | |
1139 else if (m_current < m_zeroEnd) | |
1140 { | |
1141 // XXX trying to write in zero area | |
1142 NS_ASSERT (false); | |
1143 } | |
1144 else if (m_current < m_dataEnd) | |
1145 { | |
1146 m_data[m_current - (m_zeroEnd-m_zeroStart)] = data; | |
1147 m_current++;······ | |
1148 } | |
1149 else· | |
1150 { | |
1151 // XXX trying to write outside of data area | |
1152 NS_ASSERT (false); | |
1153 } | |
1154 } | |
1155 | |
1156 void· | |
1157 Buffer::Iterator::WriteU8 (uint8_t data, uint32_t len) | |
1158 { | |
1159 for (uint32_t i = 0; i < len; i++) | |
1160 { | |
1161 WriteU8 (data); | |
1162 } | |
1163 } | |
1164 | |
1165 uint8_t·· | |
1166 Buffer::Iterator::ReadU8 (void) | |
1167 { | |
1168 if (m_current < m_dataStart) | |
1169 { | |
1170 // XXX trying to read from outside of data area | |
1171 NS_ASSERT (false); | |
1172 } | |
1173 else if (m_current < m_zeroStart) | |
1174 { | |
1175 uint8_t data = m_data[m_current]; | |
1176 m_current++; | |
1177 return data; | |
1178 } | |
1179 else if (m_current < m_zeroEnd) | |
1180 { | |
1181 m_current++; | |
1182 return 0; | |
1183 } | |
1184 else if (m_current < m_dataEnd) | |
1185 { | |
1186 uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)]; | |
1187 m_current++; | |
1188 return data; | |
1189 } | |
1190 else· | |
1191 { | |
1192 // XXX trying to read from outside of data area | |
1193 NS_ASSERT (false); | |
1194 } | |
1195 // to quiet compiler. | |
1196 return 0; | |
1197 } | |
1198 | |
1199 #endif /* BUFFER_USE_INLINE */ | |
1200 | 1287 |
1201 uint16_t | 1288 uint16_t |
1202 Buffer::Iterator::CalculateIpChecksum(uint16_t size) | 1289 Buffer::Iterator::CalculateIpChecksum(uint16_t size) |
1203 { | 1290 { |
1204 return CalculateIpChecksum(size, 0); | 1291 return CalculateIpChecksum(size, 0); |
1205 } | 1292 } |
1206 | 1293 |
1207 uint16_t | 1294 uint16_t |
1208 Buffer::Iterator::CalculateIpChecksum(uint16_t size, uint32_t initialChecksum) | 1295 Buffer::Iterator::CalculateIpChecksum(uint16_t size, uint32_t initialChecksum) |
1209 { | 1296 { |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 : TestSuite ("buffer", UNIT) | 1623 : TestSuite ("buffer", UNIT) |
1537 { | 1624 { |
1538 AddTestCase (new BufferTest); | 1625 AddTestCase (new BufferTest); |
1539 } | 1626 } |
1540 | 1627 |
1541 BufferTestSuite g_bufferTestSuite; | 1628 BufferTestSuite g_bufferTestSuite; |
1542 | 1629 |
1543 } // namespace ns3 | 1630 } // namespace ns3 |
1544 | 1631 |
1545 | 1632 |
LEFT | RIGHT |