/root/projects/repository/source/cpp/CAlfrescoApp/source/util/DataBuffer.cpp

https://github.com/deas/alfresco · C++ · 727 lines · 253 code · 183 blank · 291 comment · 35 complexity · 5a6c3090b9ac2032778e3f13cbbc09d0 MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "util\DataBuffer.h"
  20. #include "util\Exception.h"
  21. using namespace Alfresco;
  22. using namespace std;
  23. // Use a macro for buffer overflow checks
  24. #define CHECK_BUFFER(sz) {if ((( m_buflen + m_offset) - m_pos) < sz) throw ArrayIndexOutOfBoundsException(__FILE__, __LINE__, L"DataBuffer overflow"); }
  25. #define CHECK_BUFFER_POS(pos,sz) {if ((( m_buflen + m_offset) - pos) < sz) throw ArrayIndexOutOfBoundsException(__FILE__, __LINE__, L"DataBuffer overflow"); }
  26. #define EXTEND_CHECK(sz) {if ((( m_buflen + m_offset) - m_pos) < sz) extendBuffer(); }
  27. #define EXTEND_CHECK_POS(pos,sz) {if ((( m_buflen + m_offset) - pos) < sz) extendBuffer(); }
  28. /**
  29. * Class constructor
  30. *
  31. * @param siz unsigned int
  32. */
  33. DataBuffer::DataBuffer( unsigned int siz) {
  34. m_buf = new unsigned char[siz];
  35. m_buflen = siz;
  36. m_owner = true;
  37. m_pos = 0;
  38. m_endpos = 0;
  39. m_offset = 0;
  40. }
  41. /**
  42. * Class constructor
  43. *
  44. * @param buf BUFPTR
  45. * @param off BUFPOS
  46. * @param len BUFLEN
  47. */
  48. DataBuffer::DataBuffer( BUFPTR buf, BUFPOS off, BUFLEN len) {
  49. m_buf = buf;
  50. m_buflen = len;
  51. m_owner = false;
  52. m_pos = off;
  53. m_offset = off;
  54. m_endpos = off + len;
  55. }
  56. /**
  57. * Class destructor
  58. */
  59. DataBuffer::~DataBuffer() {
  60. // Delete the buffer, if owned by this object
  61. if ( m_owner == true && m_buf != NULL)
  62. delete[] m_buf;
  63. }
  64. /**
  65. * Return the buffer length
  66. *
  67. * @return BUFLEN
  68. */
  69. BUFLEN DataBuffer::getLength( void) const {
  70. if ( m_endpos != 0)
  71. return m_endpos - m_offset;
  72. return m_pos - m_offset;
  73. }
  74. /**
  75. * Return the length in words
  76. *
  77. * @return unsigned int
  78. */
  79. unsigned int DataBuffer::getLengthInWords( void) const {
  80. return getLength() / 2;
  81. }
  82. /**
  83. * Return the available buffer length
  84. *
  85. * @return BUFLEN
  86. */
  87. BUFLEN DataBuffer::getAvailableLength( void) const {
  88. if ( m_endpos == 0)
  89. return 0;
  90. return m_endpos - m_pos;
  91. }
  92. /**
  93. * Get a byte from the buffer and advance the buffer pointer
  94. *
  95. * @return unsigned char
  96. */
  97. unsigned char DataBuffer::getByte( void) {
  98. // Check if there is enough space in the buffer for the data
  99. CHECK_BUFFER(1);
  100. // Return the data
  101. return (unsigned int) m_buf[m_pos++];
  102. }
  103. /**
  104. * Get a short/16bit value from the buffer and advance the buffer pointer
  105. *
  106. * @return unsigned int
  107. */
  108. unsigned int DataBuffer::getShort( void) {
  109. // Check if there is enough space in the buffer for the data
  110. CHECK_BUFFER(2);
  111. // Get a short value from the buffer
  112. unsigned int sval = DataPacker::getIntelShort( m_buf, m_pos);
  113. m_pos += 2;
  114. return sval;
  115. }
  116. /**
  117. * Get an integer from the buffer and advance the buffer pointer
  118. *
  119. * @return unsigned int
  120. */
  121. unsigned int DataBuffer::getInt( void) {
  122. // Check if there is enough space in the buffer for the data
  123. CHECK_BUFFER(4);
  124. // Get a short value from the buffer
  125. unsigned int ival = DataPacker::getIntelInt( m_buf, m_pos);
  126. m_pos += 4;
  127. return ival;
  128. }
  129. /**
  130. * Get a long from the buffer and advance the buffer pointer
  131. *
  132. * @return LONG64
  133. */
  134. LONG64 DataBuffer::getLong( void) {
  135. // Check if there is enough space in the buffer for the data
  136. CHECK_BUFFER(8);
  137. // Get a long value from the buffer
  138. LONG64 lval = DataPacker::getIntelLong( m_buf, m_pos);
  139. m_pos += 8;
  140. return lval;
  141. }
  142. /**
  143. * Get a string from the buffer and advance the buffer pointer
  144. *
  145. * @param uni bool
  146. * @return String
  147. */
  148. String DataBuffer::getString( bool uni) {
  149. return getString( getAvailableLength(), uni);
  150. }
  151. /**
  152. * Get a string from the buffer and advance the buffer pointer
  153. *
  154. * @param maxlen unsigned int
  155. * @param uni bool
  156. * @return String
  157. */
  158. String DataBuffer::getString( unsigned int maxlen, bool uni) {
  159. // Check for Unicode or ASCII
  160. String ret;
  161. unsigned int availLen = 0;
  162. if ( uni) {
  163. // Word align the current buffer position, calculate the available length
  164. m_pos = DataPacker::wordAlign(m_pos);
  165. availLen = (m_endpos - m_pos) / 2;
  166. if ( availLen < maxlen)
  167. maxlen = availLen;
  168. ret = DataPacker::getUnicodeString(m_buf, m_pos, maxlen);
  169. if ( ret.length() < maxlen)
  170. m_pos += (ret.length() * 2) + 2;
  171. else
  172. m_pos += maxlen * 2;
  173. }
  174. else {
  175. // Calculate the available length
  176. availLen = m_endpos - m_pos;
  177. if ( availLen < maxlen)
  178. maxlen = availLen;
  179. // Unpack the ASCII string
  180. ret = DataPacker::getString(m_buf, m_pos, maxlen);
  181. if ( ret.length() < maxlen)
  182. m_pos += ret.length() + 1;
  183. else
  184. m_pos += maxlen;
  185. }
  186. // Return the string
  187. return ret;
  188. }
  189. /**
  190. * Get a short value at the specified buffer position
  191. *
  192. * @param idx unsigned int
  193. * @return unsigned int
  194. */
  195. unsigned int DataBuffer::getShortAt( unsigned int idx) {
  196. // Check if there is enough data in the buffer
  197. BUFPOS pos = m_offset + (idx * 2);
  198. CHECK_BUFFER_POS(pos, 2);
  199. // Unpack the short value
  200. return DataPacker::getIntelShort(m_buf, pos);
  201. }
  202. /**
  203. * Get an integer value at the specified buffer position
  204. *
  205. * @param idx unsigned int
  206. * @return unsigned int
  207. */
  208. unsigned int DataBuffer::getIntAt( unsigned int idx) {
  209. // Check if there is enough data in the buffer
  210. BUFPOS pos = m_offset + (idx * 4);
  211. CHECK_BUFFER_POS(pos, 4);
  212. // Unpack the integer value
  213. return DataPacker::getIntelInt(m_buf, pos);
  214. }
  215. /**
  216. * Get a long value at the specified buffer position
  217. *
  218. * @param idx unsigned int
  219. * @return LONG64
  220. */
  221. LONG64 DataBuffer::getLongAt( unsigned int idx) {
  222. // Check if there is enough data in the buffer
  223. BUFPOS pos = m_offset + (idx * 8);
  224. CHECK_BUFFER_POS(pos, 8);
  225. // Unpack the long value
  226. return DataPacker::getIntelLong(m_buf, pos);
  227. }
  228. /**
  229. * Append a byte to the buffer and advance the buffer pointer
  230. *
  231. * @param byt unsigned char
  232. */
  233. void DataBuffer::putByte( unsigned char byt) {
  234. // Check if the buffer needs extending
  235. EXTEND_CHECK(1);
  236. // Pack the data, update the buffer pointer
  237. m_buf[m_pos++] = byt;
  238. }
  239. /**
  240. * Append a short to the buffer and advance the buffer pointer
  241. *
  242. * @param sval unsigned int
  243. */
  244. void DataBuffer::putShort( unsigned int sval) {
  245. // Check if the buffer needs extending
  246. EXTEND_CHECK(2);
  247. // Pack the data, update the buffer pointer
  248. DataPacker::putIntelShort( sval, m_buf, m_pos);
  249. m_pos += 2;
  250. }
  251. /**
  252. * Append an integer to the buffer and advance the buffer pointer
  253. *
  254. * @param ival unsigned int
  255. */
  256. void DataBuffer::putInt( unsigned int ival) {
  257. // Check if the buffer needs extending
  258. EXTEND_CHECK(4);
  259. // Pack the data, update the buffer pointer
  260. DataPacker::putIntelInt( ival, m_buf, m_pos);
  261. m_pos += 4;
  262. }
  263. /**
  264. * Append a long to the buffer and advance the buffer pointer
  265. *
  266. * @param lval LONG64
  267. */
  268. void DataBuffer::putLong( LONG64 lval) {
  269. // Check if the buffer needs extending
  270. EXTEND_CHECK(8);
  271. // Pack the data, update the buffer pointer
  272. DataPacker::putIntelLong( lval, m_buf, m_pos);
  273. m_pos += 8;
  274. }
  275. /**
  276. * Put a short value into the buffer at the specified position
  277. *
  278. * @param idx unsigned int
  279. * @param sval unsigned int
  280. */
  281. void DataBuffer::putShortAt( unsigned int idx, unsigned int sval) {
  282. // Check if there is enough space in the buffer
  283. BUFPOS pos = m_offset + (idx * 2);
  284. EXTEND_CHECK_POS(pos,2);
  285. // Pack the short value
  286. DataPacker::putIntelShort(sval, m_buf, pos);
  287. }
  288. /**
  289. * Put an integer value into the buffer at the specified position
  290. *
  291. * @param idx unsigned int
  292. * @param ival unsigned int
  293. */
  294. void DataBuffer::putIntAt( unsigned int idx, unsigned int ival) {
  295. // Check if there is enough space in the buffer
  296. BUFPOS pos = m_offset + (idx * 4);
  297. EXTEND_CHECK_POS(pos,4);
  298. // Pack the integer value
  299. DataPacker::putIntelInt(ival, m_buf, pos);
  300. }
  301. /**
  302. * Put a long value into the buffer at the specified position
  303. *
  304. * @param idx unsigned int
  305. * @param lval LONG64
  306. */
  307. void DataBuffer::putLongAt( unsigned int idx, LONG64 lval) {
  308. // Check if there is enough space in the buffer
  309. BUFPOS pos = m_offset + (idx * 8);
  310. EXTEND_CHECK_POS(pos,8);
  311. // Pack the long value
  312. DataPacker::putIntelLong(lval, m_buf, pos);
  313. }
  314. /**
  315. * Append a string to the buffer and advance the buffer pointer
  316. *
  317. * @param str const String&
  318. * @param uni bool
  319. * @param nulTerm bool
  320. */
  321. void DataBuffer::putString( const String& str, bool uni, bool nulTerm) {
  322. // Check for Unicode or ASCII
  323. if ( uni) {
  324. // Check if there is enough space in the buffer
  325. unsigned int bytLen = str.length() * 2;
  326. if ( m_buflen - m_pos < bytLen)
  327. extendBuffer(bytLen + 4);
  328. // Word align the buffer position, pack the Unicode string
  329. m_pos = DataPacker::wordAlign(m_pos);
  330. DataPacker::putString(str, m_buf, m_pos, nulTerm, true);
  331. m_pos += (str.length() * 2);
  332. if ( nulTerm)
  333. m_pos += 2;
  334. }
  335. else {
  336. // Check if there is enough space in the buffer
  337. if ( m_buflen - m_pos < str.length())
  338. extendBuffer(str.length() + 2);
  339. // Pack the ASCII string
  340. DataPacker::putString(str, m_buf, m_pos, nulTerm);
  341. m_pos += str.length();
  342. if ( nulTerm)
  343. m_pos++;
  344. }
  345. }
  346. /**
  347. * Append a fixed length string to the buffer and advance the buffer pointer
  348. *
  349. * @param str const String&
  350. * @param len unsigned int
  351. */
  352. void DataBuffer::putFixedString( const String& str, unsigned int len) {
  353. // Check if there is enough space in the buffer
  354. if ( m_buflen - m_pos < str.length())
  355. extendBuffer(str.length() + 2);
  356. // Pack the ASCII string
  357. DataPacker::putString(str, m_buf, m_pos);
  358. m_pos += len;
  359. // Pad the string to the required length
  360. while ( len > str.length()) {
  361. m_buf[m_pos++] = 0;
  362. len--;
  363. }
  364. }
  365. /**
  366. * Put a string into the buffer at the specified position
  367. *
  368. * @param str const String&
  369. * @param pos BUFPOS
  370. * @param uni bool
  371. * @param nulTerm bool
  372. * @return BUFPOS
  373. */
  374. BUFPOS DataBuffer::putStringAt( const String& str, BUFPOS pos, bool uni, bool nulTerm) {
  375. // Check for Unicode or ASCII
  376. BUFPOS retPos = 0;
  377. if ( uni) {
  378. // Check if there is enough space in the buffer
  379. unsigned int bytLen = str.length() * 2;
  380. if ( m_buflen - pos < bytLen)
  381. extendBuffer(bytLen + 4);
  382. // Word align the buffer position, pack the Unicode string
  383. pos = DataPacker::wordAlign(pos);
  384. retPos = DataPacker::putString(str, m_buf, pos, nulTerm);
  385. }
  386. else {
  387. // Check if there is enough space in the buffer
  388. if ( m_buflen - pos < str.length())
  389. extendBuffer(str.length() + 2);
  390. // Pack the ASCII string
  391. retPos = DataPacker::putString(str, m_buf, pos, nulTerm);
  392. }
  393. // Return the end of string buffer position
  394. return retPos;
  395. }
  396. /**
  397. * Put a fixed length string into the buffer at the specified position
  398. *
  399. * @param str const String&
  400. * @param len unsigned int
  401. * @param pos BUFPOS
  402. * @return BUFPOS
  403. */
  404. BUFPOS DataBuffer::putFixedStringAt( const String& str, unsigned int len, BUFPOS pos) {
  405. // Check if there is enough space in the buffer
  406. if ( m_buflen - pos < str.length())
  407. extendBuffer(str.length() + 2);
  408. // Pack the ASCII string
  409. pos = DataPacker::putString(str, m_buf, pos);
  410. // Pad the string
  411. while ( len > str.length()) {
  412. m_buf[pos++] = 0;
  413. len--;
  414. }
  415. // Return the end of string buffer position
  416. return pos;
  417. }
  418. /**
  419. * Put a string pointer into the buffer
  420. *
  421. * @param off unsigned int
  422. */
  423. void DataBuffer::putStringPointer( unsigned int off) {
  424. // Calculate the offset from the start of the data buffer to the string position
  425. DataPacker::putIntelInt(off - m_offset, m_buf, m_pos);
  426. m_pos += 4;
  427. }
  428. /**
  429. * Append a block of nulls to the buffer and advance the buffer pointer
  430. *
  431. * @param cnt unsigned int
  432. */
  433. void DataBuffer::putZeros( unsigned int cnt) {
  434. // Check if there is enough space in the buffer
  435. if ( m_buflen - m_pos < cnt)
  436. extendBuffer(cnt);
  437. // Pack the zero bytes
  438. for ( unsigned int i = 0; i < cnt; i++)
  439. m_buf[m_pos++] = 0;
  440. }
  441. /**
  442. * Word align the buffer pointer
  443. *
  444. */
  445. void DataBuffer::wordAlign( void) {
  446. m_pos = DataPacker::wordAlign(m_pos);
  447. }
  448. /**
  449. * Longword align the buffer pointer
  450. *
  451. */
  452. void DataBuffer::longwordAlign( void) {
  453. m_pos = DataPacker::longwordAlign(m_pos);
  454. }
  455. /**
  456. * Append a block of byte data to the buffer and advance the buffer pointer
  457. *
  458. * @param buf BUFPTR
  459. * @param off BUFPOS
  460. * @param len BUFLEN
  461. */
  462. void DataBuffer::appendData( BUFPTR buf, BUFPOS off, BUFLEN len) {
  463. // Check if there is enough space in the buffer
  464. if ( m_buflen - m_pos < len)
  465. extendBuffer(len);
  466. // Copy the data to the buffer and update the current write position
  467. memcpy( m_buf + m_pos, buf + off, len);
  468. m_pos += len;
  469. }
  470. /**
  471. * Copy data to the user buffer and advance the buffer pointer
  472. *
  473. * @param buf BUFPTR
  474. * @param pos BUFPOS
  475. * @param cnt unsigned int
  476. */
  477. unsigned int DataBuffer::copyData( BUFPTR buf, BUFPOS pos, unsigned int cnt) {
  478. // Check if there is any more data to copy
  479. if ( m_pos == m_endpos)
  480. return 0;
  481. // Calculate the amount of data to copy
  482. unsigned int siz = m_endpos - m_pos;
  483. if ( siz > cnt)
  484. siz = cnt;
  485. // Copy the data to the user buffer and update the current read position
  486. memcpy( buf + pos, m_buf + m_pos, siz);
  487. m_pos += siz;
  488. // Return the amount of data copied
  489. return siz;
  490. }
  491. /**
  492. * Advance the buffer pointer by the specified amount
  493. *
  494. * @param len unsigned int
  495. */
  496. void DataBuffer::skipBytes( unsigned int len) {
  497. // Check if there is enough data in the buffer
  498. CHECK_BUFFER(len);
  499. // Skip bytes
  500. m_pos += len;
  501. }
  502. /**
  503. * Set the end of buffer position
  504. */
  505. void DataBuffer::setEndOfBuffer( void) {
  506. m_endpos = m_pos;
  507. m_pos = m_offset;
  508. }
  509. /**
  510. * Set the buffer length
  511. *
  512. * @param len BUFLEN
  513. */
  514. void DataBuffer::setLength( BUFLEN len) {
  515. m_pos = m_offset + len;
  516. }
  517. /**
  518. * Extend the buffer by the specified amount by reallocating the buffer and copying the existing
  519. * data to the new buffer
  520. *
  521. * @param ext BUFLEN
  522. */
  523. void DataBuffer::extendBuffer( BUFLEN ext) {
  524. // Create a new buffer of the required size
  525. BUFLEN newlen = m_buflen + ext;
  526. BUFPTR newBuf = new unsigned char[newlen];
  527. // Copy the data from the current buffer to the new buffer
  528. memcpy( newBuf, m_buf, m_buflen);
  529. // Check if the previous buffer was owned by this object
  530. if ( m_owner)
  531. delete[] m_buf;
  532. // Set the new buffer to be the main buffer
  533. m_buf = newBuf;
  534. m_buflen = newlen;
  535. m_owner = true;
  536. }
  537. /**
  538. * Extend the buffer doubling the current size by reallocating the buffer and copying the existing
  539. * data to the new buffer
  540. *
  541. */
  542. void DataBuffer::extendBuffer( void) {
  543. extendBuffer( m_buflen * 2);
  544. }