Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

565 lines
12 KiB

  1. // queue.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_IMPORTS
  4. #include "queue.h"
  5. #include "filters.h"
  6. NAMESPACE_BEGIN(CryptoPP)
  7. static const unsigned int s_maxAutoNodeSize = 16*1024;
  8. // this class for use by ByteQueue only
  9. class ByteQueueNode
  10. {
  11. public:
  12. ByteQueueNode(size_t maxSize)
  13. : buf(maxSize)
  14. {
  15. m_head = m_tail = 0;
  16. next = 0;
  17. }
  18. inline size_t MaxSize() const {return buf.size();}
  19. inline size_t CurrentSize() const
  20. {
  21. return m_tail-m_head;
  22. }
  23. inline bool UsedUp() const
  24. {
  25. return (m_head==MaxSize());
  26. }
  27. inline void Clear()
  28. {
  29. m_head = m_tail = 0;
  30. }
  31. inline size_t Put(const byte *begin, size_t length)
  32. {
  33. size_t l = STDMIN(length, MaxSize()-m_tail);
  34. if (buf+m_tail != begin)
  35. memcpy(buf+m_tail, begin, l);
  36. m_tail += l;
  37. return l;
  38. }
  39. inline size_t Peek(byte &outByte) const
  40. {
  41. if (m_tail==m_head)
  42. return 0;
  43. outByte=buf[m_head];
  44. return 1;
  45. }
  46. inline size_t Peek(byte *target, size_t copyMax) const
  47. {
  48. size_t len = STDMIN(copyMax, m_tail-m_head);
  49. memcpy(target, buf+m_head, len);
  50. return len;
  51. }
  52. inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const
  53. {
  54. size_t len = m_tail-m_head;
  55. target.ChannelPut(channel, buf+m_head, len);
  56. return len;
  57. }
  58. inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const
  59. {
  60. size_t len = STDMIN(copyMax, m_tail-m_head);
  61. target.ChannelPut(channel, buf+m_head, len);
  62. return len;
  63. }
  64. inline size_t Get(byte &outByte)
  65. {
  66. size_t len = Peek(outByte);
  67. m_head += len;
  68. return len;
  69. }
  70. inline size_t Get(byte *outString, size_t getMax)
  71. {
  72. size_t len = Peek(outString, getMax);
  73. m_head += len;
  74. return len;
  75. }
  76. inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
  77. {
  78. size_t len = m_tail-m_head;
  79. target.ChannelPutModifiable(channel, buf+m_head, len);
  80. m_head = m_tail;
  81. return len;
  82. }
  83. inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL)
  84. {
  85. size_t len = UnsignedMin(m_tail-m_head, transferMax);
  86. target.ChannelPutModifiable(channel, buf+m_head, len);
  87. m_head += len;
  88. return len;
  89. }
  90. inline size_t Skip(size_t skipMax)
  91. {
  92. size_t len = STDMIN(skipMax, m_tail-m_head);
  93. m_head += len;
  94. return len;
  95. }
  96. inline byte operator[](size_t i) const
  97. {
  98. return buf[m_head+i];
  99. }
  100. ByteQueueNode *next;
  101. SecByteBlock buf;
  102. size_t m_head, m_tail;
  103. };
  104. // ********************************************************
  105. ByteQueue::ByteQueue(size_t nodeSize)
  106. : m_lazyString(NULL), m_lazyLength(0)
  107. {
  108. SetNodeSize(nodeSize);
  109. m_head = m_tail = new ByteQueueNode(m_nodeSize);
  110. }
  111. void ByteQueue::SetNodeSize(size_t nodeSize)
  112. {
  113. m_autoNodeSize = !nodeSize;
  114. m_nodeSize = m_autoNodeSize ? 256 : nodeSize;
  115. }
  116. ByteQueue::ByteQueue(const ByteQueue &copy)
  117. : m_lazyString(NULL)
  118. {
  119. CopyFrom(copy);
  120. }
  121. void ByteQueue::CopyFrom(const ByteQueue &copy)
  122. {
  123. m_lazyLength = 0;
  124. m_autoNodeSize = copy.m_autoNodeSize;
  125. m_nodeSize = copy.m_nodeSize;
  126. m_head = m_tail = new ByteQueueNode(*copy.m_head);
  127. for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
  128. {
  129. m_tail->next = new ByteQueueNode(*current);
  130. m_tail = m_tail->next;
  131. }
  132. m_tail->next = NULL;
  133. Put(copy.m_lazyString, copy.m_lazyLength);
  134. }
  135. ByteQueue::~ByteQueue()
  136. {
  137. Destroy();
  138. }
  139. void ByteQueue::Destroy()
  140. {
  141. for (ByteQueueNode *next, *current=m_head; current; current=next)
  142. {
  143. next=current->next;
  144. delete current;
  145. }
  146. }
  147. void ByteQueue::IsolatedInitialize(const NameValuePairs &parameters)
  148. {
  149. m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
  150. Clear();
  151. }
  152. lword ByteQueue::CurrentSize() const
  153. {
  154. lword size=0;
  155. for (ByteQueueNode *current=m_head; current; current=current->next)
  156. size += current->CurrentSize();
  157. return size + m_lazyLength;
  158. }
  159. bool ByteQueue::IsEmpty() const
  160. {
  161. return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
  162. }
  163. void ByteQueue::Clear()
  164. {
  165. for (ByteQueueNode *next, *current=m_head->next; current; current=next)
  166. {
  167. next=current->next;
  168. delete current;
  169. }
  170. m_tail = m_head;
  171. m_head->Clear();
  172. m_head->next = NULL;
  173. m_lazyLength = 0;
  174. }
  175. size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
  176. {
  177. if (m_lazyLength > 0)
  178. FinalizeLazyPut();
  179. size_t len;
  180. while ((len=m_tail->Put(inString, length)) < length)
  181. {
  182. inString += len;
  183. length -= len;
  184. if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize)
  185. do
  186. {
  187. m_nodeSize *= 2;
  188. }
  189. while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize);
  190. m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length));
  191. m_tail = m_tail->next;
  192. }
  193. return 0;
  194. }
  195. void ByteQueue::CleanupUsedNodes()
  196. {
  197. while (m_head != m_tail && m_head->UsedUp())
  198. {
  199. ByteQueueNode *temp=m_head;
  200. m_head=m_head->next;
  201. delete temp;
  202. }
  203. if (m_head->CurrentSize() == 0)
  204. m_head->Clear();
  205. }
  206. void ByteQueue::LazyPut(const byte *inString, size_t size)
  207. {
  208. if (m_lazyLength > 0)
  209. FinalizeLazyPut();
  210. if (inString == m_tail->buf+m_tail->m_tail)
  211. Put(inString, size);
  212. else
  213. {
  214. m_lazyString = const_cast<byte *>(inString);
  215. m_lazyLength = size;
  216. m_lazyStringModifiable = false;
  217. }
  218. }
  219. void ByteQueue::LazyPutModifiable(byte *inString, size_t size)
  220. {
  221. if (m_lazyLength > 0)
  222. FinalizeLazyPut();
  223. m_lazyString = inString;
  224. m_lazyLength = size;
  225. m_lazyStringModifiable = true;
  226. }
  227. void ByteQueue::UndoLazyPut(size_t size)
  228. {
  229. if (m_lazyLength < size)
  230. throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
  231. m_lazyLength -= size;
  232. }
  233. void ByteQueue::FinalizeLazyPut()
  234. {
  235. size_t len = m_lazyLength;
  236. m_lazyLength = 0;
  237. if (len)
  238. Put(m_lazyString, len);
  239. }
  240. size_t ByteQueue::Get(byte &outByte)
  241. {
  242. if (m_head->Get(outByte))
  243. {
  244. if (m_head->UsedUp())
  245. CleanupUsedNodes();
  246. return 1;
  247. }
  248. else if (m_lazyLength > 0)
  249. {
  250. outByte = *m_lazyString++;
  251. m_lazyLength--;
  252. return 1;
  253. }
  254. else
  255. return 0;
  256. }
  257. size_t ByteQueue::Get(byte *outString, size_t getMax)
  258. {
  259. ArraySink sink(outString, getMax);
  260. return (size_t)TransferTo(sink, getMax);
  261. }
  262. size_t ByteQueue::Peek(byte &outByte) const
  263. {
  264. if (m_head->Peek(outByte))
  265. return 1;
  266. else if (m_lazyLength > 0)
  267. {
  268. outByte = *m_lazyString;
  269. return 1;
  270. }
  271. else
  272. return 0;
  273. }
  274. size_t ByteQueue::Peek(byte *outString, size_t peekMax) const
  275. {
  276. ArraySink sink(outString, peekMax);
  277. return (size_t)CopyTo(sink, peekMax);
  278. }
  279. size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
  280. {
  281. if (blocking)
  282. {
  283. lword bytesLeft = transferBytes;
  284. for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
  285. bytesLeft -= current->TransferTo(target, bytesLeft, channel);
  286. CleanupUsedNodes();
  287. size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
  288. if (len)
  289. {
  290. if (m_lazyStringModifiable)
  291. target.ChannelPutModifiable(channel, m_lazyString, len);
  292. else
  293. target.ChannelPut(channel, m_lazyString, len);
  294. m_lazyString += len;
  295. m_lazyLength -= len;
  296. bytesLeft -= len;
  297. }
  298. transferBytes -= bytesLeft;
  299. return 0;
  300. }
  301. else
  302. {
  303. Walker walker(*this);
  304. size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
  305. Skip(transferBytes);
  306. return blockedBytes;
  307. }
  308. }
  309. size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
  310. {
  311. Walker walker(*this);
  312. walker.Skip(begin);
  313. lword transferBytes = end-begin;
  314. size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
  315. begin += transferBytes;
  316. return blockedBytes;
  317. }
  318. void ByteQueue::Unget(byte inByte)
  319. {
  320. Unget(&inByte, 1);
  321. }
  322. void ByteQueue::Unget(const byte *inString, size_t length)
  323. {
  324. size_t len = STDMIN(length, m_head->m_head);
  325. length -= len;
  326. m_head->m_head -= len;
  327. memcpy(m_head->buf + m_head->m_head, inString + length, len);
  328. if (length > 0)
  329. {
  330. ByteQueueNode *newHead = new ByteQueueNode(length);
  331. newHead->next = m_head;
  332. m_head = newHead;
  333. m_head->Put(inString, length);
  334. }
  335. }
  336. const byte * ByteQueue::Spy(size_t &contiguousSize) const
  337. {
  338. contiguousSize = m_head->m_tail - m_head->m_head;
  339. if (contiguousSize == 0 && m_lazyLength > 0)
  340. {
  341. contiguousSize = m_lazyLength;
  342. return m_lazyString;
  343. }
  344. else
  345. return m_head->buf + m_head->m_head;
  346. }
  347. byte * ByteQueue::CreatePutSpace(size_t &size)
  348. {
  349. if (m_lazyLength > 0)
  350. FinalizeLazyPut();
  351. if (m_tail->m_tail == m_tail->MaxSize())
  352. {
  353. m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size));
  354. m_tail = m_tail->next;
  355. }
  356. size = m_tail->MaxSize() - m_tail->m_tail;
  357. return m_tail->buf + m_tail->m_tail;
  358. }
  359. ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
  360. {
  361. Destroy();
  362. CopyFrom(rhs);
  363. return *this;
  364. }
  365. bool ByteQueue::operator==(const ByteQueue &rhs) const
  366. {
  367. const lword currentSize = CurrentSize();
  368. if (currentSize != rhs.CurrentSize())
  369. return false;
  370. Walker walker1(*this), walker2(rhs);
  371. byte b1, b2;
  372. while (walker1.Get(b1) && walker2.Get(b2))
  373. if (b1 != b2)
  374. return false;
  375. return true;
  376. }
  377. byte ByteQueue::operator[](lword i) const
  378. {
  379. for (ByteQueueNode *current=m_head; current; current=current->next)
  380. {
  381. if (i < current->CurrentSize())
  382. return (*current)[(size_t)i];
  383. i -= current->CurrentSize();
  384. }
  385. assert(i < m_lazyLength);
  386. return m_lazyString[i];
  387. }
  388. void ByteQueue::swap(ByteQueue &rhs)
  389. {
  390. std::swap(m_autoNodeSize, rhs.m_autoNodeSize);
  391. std::swap(m_nodeSize, rhs.m_nodeSize);
  392. std::swap(m_head, rhs.m_head);
  393. std::swap(m_tail, rhs.m_tail);
  394. std::swap(m_lazyString, rhs.m_lazyString);
  395. std::swap(m_lazyLength, rhs.m_lazyLength);
  396. std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable);
  397. }
  398. // ********************************************************
  399. void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs &parameters)
  400. {
  401. m_node = m_queue.m_head;
  402. m_position = 0;
  403. m_offset = 0;
  404. m_lazyString = m_queue.m_lazyString;
  405. m_lazyLength = m_queue.m_lazyLength;
  406. }
  407. size_t ByteQueue::Walker::Get(byte &outByte)
  408. {
  409. ArraySink sink(&outByte, 1);
  410. return (size_t)TransferTo(sink, 1);
  411. }
  412. size_t ByteQueue::Walker::Get(byte *outString, size_t getMax)
  413. {
  414. ArraySink sink(outString, getMax);
  415. return (size_t)TransferTo(sink, getMax);
  416. }
  417. size_t ByteQueue::Walker::Peek(byte &outByte) const
  418. {
  419. ArraySink sink(&outByte, 1);
  420. return (size_t)CopyTo(sink, 1);
  421. }
  422. size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const
  423. {
  424. ArraySink sink(outString, peekMax);
  425. return (size_t)CopyTo(sink, peekMax);
  426. }
  427. size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
  428. {
  429. lword bytesLeft = transferBytes;
  430. size_t blockedBytes = 0;
  431. while (m_node)
  432. {
  433. size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset);
  434. blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
  435. if (blockedBytes)
  436. goto done;
  437. m_position += len;
  438. bytesLeft -= len;
  439. if (!bytesLeft)
  440. {
  441. m_offset += len;
  442. goto done;
  443. }
  444. m_node = m_node->next;
  445. m_offset = 0;
  446. }
  447. if (bytesLeft && m_lazyLength)
  448. {
  449. size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
  450. blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
  451. if (blockedBytes)
  452. goto done;
  453. m_lazyString += len;
  454. m_lazyLength -= len;
  455. bytesLeft -= len;
  456. }
  457. done:
  458. transferBytes -= bytesLeft;
  459. return blockedBytes;
  460. }
  461. size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
  462. {
  463. Walker walker(*this);
  464. walker.Skip(begin);
  465. lword transferBytes = end-begin;
  466. size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
  467. begin += transferBytes;
  468. return blockedBytes;
  469. }
  470. NAMESPACE_END
  471. #endif