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.

InStream.h 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. //
  19. // rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
  20. // Representation).
  21. //
  22. #ifndef __RDR_INSTREAM_H__
  23. #define __RDR_INSTREAM_H__
  24. #include <rdr/types.h>
  25. #include <string.h> // for memcpy
  26. namespace rdr {
  27. class InStream {
  28. public:
  29. virtual ~InStream() {}
  30. // check() ensures there is buffer data for at least one item of size
  31. // itemSize bytes. Returns the number of items in the buffer (up to a
  32. // maximum of nItems). If wait is false, then instead of blocking to wait
  33. // for the bytes, zero is returned if the bytes are not immediately
  34. // available.
  35. inline int check(int itemSize, int nItems=1, bool wait=true)
  36. {
  37. if (ptr + itemSize * nItems > end) {
  38. if (ptr + itemSize > end)
  39. return overrun(itemSize, nItems, wait);
  40. nItems = (end - ptr) / itemSize;
  41. }
  42. return nItems;
  43. }
  44. // checkNoWait() tries to make sure that the given number of bytes can
  45. // be read without blocking. It returns true if this is the case, false
  46. // otherwise. The length must be "small" (less than the buffer size).
  47. inline bool checkNoWait(int length) { return check(length, 1, false)!=0; }
  48. // readU/SN() methods read unsigned and signed N-bit integers.
  49. inline U8 readU8() { check(1); return *ptr++; }
  50. inline U16 readU16() { check(2); int b0 = *ptr++; int b1 = *ptr++;
  51. return b0 << 8 | b1; }
  52. inline U32 readU32() { check(4); int b0 = *ptr++; int b1 = *ptr++;
  53. int b2 = *ptr++; int b3 = *ptr++;
  54. return b0 << 24 | b1 << 16 | b2 << 8 | b3; }
  55. inline S8 readS8() { return (S8) readU8(); }
  56. inline S16 readS16() { return (S16)readU16(); }
  57. inline S32 readS32() { return (S32)readU32(); }
  58. // readString() reads a string - a U32 length followed by the data.
  59. // Returns a null-terminated string - the caller should delete[] it
  60. // afterwards.
  61. char* readString();
  62. // maxStringLength protects against allocating a huge buffer. Set it
  63. // higher if you need longer strings.
  64. static U32 maxStringLength;
  65. inline void skip(int bytes) {
  66. while (bytes > 0) {
  67. int n = check(1, bytes);
  68. ptr += n;
  69. bytes -= n;
  70. }
  71. }
  72. // readBytes() reads an exact number of bytes.
  73. virtual void readBytes(void* data, int length) {
  74. U8* dataPtr = (U8*)data;
  75. U8* dataEnd = dataPtr + length;
  76. while (dataPtr < dataEnd) {
  77. int n = check(1, dataEnd - dataPtr);
  78. memcpy(dataPtr, ptr, n);
  79. ptr += n;
  80. dataPtr += n;
  81. }
  82. }
  83. // readOpaqueN() reads a quantity without byte-swapping.
  84. inline U8 readOpaque8() { return readU8(); }
  85. inline U16 readOpaque16() { check(2); U16 r; ((U8*)&r)[0] = *ptr++;
  86. ((U8*)&r)[1] = *ptr++; return r; }
  87. inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++;
  88. ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
  89. ((U8*)&r)[3] = *ptr++; return r; }
  90. inline U32 readOpaque24A() { check(3); U32 r=0; ((U8*)&r)[0] = *ptr++;
  91. ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
  92. return r; }
  93. inline U32 readOpaque24B() { check(3); U32 r=0; ((U8*)&r)[1] = *ptr++;
  94. ((U8*)&r)[2] = *ptr++; ((U8*)&r)[3] = *ptr++;
  95. return r; }
  96. // pos() returns the position in the stream.
  97. virtual int pos() = 0;
  98. // getptr(), getend() and setptr() are "dirty" methods which allow you to
  99. // manipulate the buffer directly. This is useful for a stream which is a
  100. // wrapper around an underlying stream.
  101. inline const U8* getptr() const { return ptr; }
  102. inline const U8* getend() const { return end; }
  103. inline void setptr(const U8* p) { ptr = p; }
  104. private:
  105. // overrun() is implemented by a derived class to cope with buffer overrun.
  106. // It ensures there are at least itemSize bytes of buffer data. Returns
  107. // the number of items in the buffer (up to a maximum of nItems). itemSize
  108. // is supposed to be "small" (a few bytes). If wait is false, then
  109. // instead of blocking to wait for the bytes, zero is returned if the bytes
  110. // are not immediately available.
  111. virtual int overrun(int itemSize, int nItems, bool wait=true) = 0;
  112. protected:
  113. InStream() {}
  114. const U8* ptr;
  115. const U8* end;
  116. };
  117. }
  118. #endif