The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

323 lines
8.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #if JUCE_DEBUG
  19. struct DanglingStreamChecker
  20. {
  21. DanglingStreamChecker() {}
  22. ~DanglingStreamChecker()
  23. {
  24. /*
  25. It's always a bad idea to leak any object, but if you're leaking output
  26. streams, then there's a good chance that you're failing to flush a file
  27. to disk properly, which could result in corrupted data and other similar
  28. nastiness..
  29. */
  30. jassert (activeStreams.size() == 0);
  31. }
  32. Array<void*, CriticalSection> activeStreams;
  33. };
  34. static DanglingStreamChecker danglingStreamChecker;
  35. #endif
  36. //==============================================================================
  37. OutputStream::OutputStream()
  38. : newLineString (NewLine::getDefault())
  39. {
  40. #if JUCE_DEBUG
  41. danglingStreamChecker.activeStreams.add (this);
  42. #endif
  43. }
  44. OutputStream::~OutputStream()
  45. {
  46. #if JUCE_DEBUG
  47. danglingStreamChecker.activeStreams.removeFirstMatchingValue (this);
  48. #endif
  49. }
  50. //==============================================================================
  51. void OutputStream::writeBool (const bool b)
  52. {
  53. writeByte (b ? (char) 1
  54. : (char) 0);
  55. }
  56. void OutputStream::writeByte (char byte)
  57. {
  58. write (&byte, 1);
  59. }
  60. void OutputStream::writeRepeatedByte (uint8 byte, int numTimesToRepeat)
  61. {
  62. while (--numTimesToRepeat >= 0)
  63. writeByte ((char) byte);
  64. }
  65. void OutputStream::writeShort (short value)
  66. {
  67. const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value);
  68. write (&v, 2);
  69. }
  70. void OutputStream::writeShortBigEndian (short value)
  71. {
  72. const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value);
  73. write (&v, 2);
  74. }
  75. void OutputStream::writeInt (int value)
  76. {
  77. const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value);
  78. write (&v, 4);
  79. }
  80. void OutputStream::writeIntBigEndian (int value)
  81. {
  82. const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value);
  83. write (&v, 4);
  84. }
  85. void OutputStream::writeCompressedInt (int value)
  86. {
  87. unsigned int un = (value < 0) ? (unsigned int) -value
  88. : (unsigned int) value;
  89. uint8 data[5];
  90. int num = 0;
  91. while (un > 0)
  92. {
  93. data[++num] = (uint8) un;
  94. un >>= 8;
  95. }
  96. data[0] = (uint8) num;
  97. if (value < 0)
  98. data[0] |= 0x80;
  99. write (data, num + 1);
  100. }
  101. void OutputStream::writeInt64 (int64 value)
  102. {
  103. const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value);
  104. write (&v, 8);
  105. }
  106. void OutputStream::writeInt64BigEndian (int64 value)
  107. {
  108. const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value);
  109. write (&v, 8);
  110. }
  111. void OutputStream::writeFloat (float value)
  112. {
  113. union { int asInt; float asFloat; } n;
  114. n.asFloat = value;
  115. writeInt (n.asInt);
  116. }
  117. void OutputStream::writeFloatBigEndian (float value)
  118. {
  119. union { int asInt; float asFloat; } n;
  120. n.asFloat = value;
  121. writeIntBigEndian (n.asInt);
  122. }
  123. void OutputStream::writeDouble (double value)
  124. {
  125. union { int64 asInt; double asDouble; } n;
  126. n.asDouble = value;
  127. writeInt64 (n.asInt);
  128. }
  129. void OutputStream::writeDoubleBigEndian (double value)
  130. {
  131. union { int64 asInt; double asDouble; } n;
  132. n.asDouble = value;
  133. writeInt64BigEndian (n.asInt);
  134. }
  135. void OutputStream::writeString (const String& text)
  136. {
  137. // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind
  138. // if lots of large, persistent strings were to be written to streams).
  139. const int numBytes = text.getNumBytesAsUTF8() + 1;
  140. HeapBlock<char> temp ((size_t) numBytes);
  141. text.copyToUTF8 (temp, numBytes);
  142. write (temp, numBytes);
  143. }
  144. void OutputStream::writeText (const String& text, const bool asUTF16,
  145. const bool writeUTF16ByteOrderMark)
  146. {
  147. if (asUTF16)
  148. {
  149. if (writeUTF16ByteOrderMark)
  150. write ("\x0ff\x0fe", 2);
  151. String::CharPointerType src (text.getCharPointer());
  152. bool lastCharWasReturn = false;
  153. for (;;)
  154. {
  155. const juce_wchar c = src.getAndAdvance();
  156. if (c == 0)
  157. break;
  158. if (c == '\n' && ! lastCharWasReturn)
  159. writeShort ((short) '\r');
  160. lastCharWasReturn = (c == L'\r');
  161. writeShort ((short) c);
  162. }
  163. }
  164. else
  165. {
  166. const char* src = text.toUTF8();
  167. const char* t = src;
  168. for (;;)
  169. {
  170. if (*t == '\n')
  171. {
  172. if (t > src)
  173. write (src, (int) (t - src));
  174. write ("\r\n", 2);
  175. src = t + 1;
  176. }
  177. else if (*t == '\r')
  178. {
  179. if (t[1] == '\n')
  180. ++t;
  181. }
  182. else if (*t == 0)
  183. {
  184. if (t > src)
  185. write (src, (int) (t - src));
  186. break;
  187. }
  188. ++t;
  189. }
  190. }
  191. }
  192. int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite)
  193. {
  194. if (numBytesToWrite < 0)
  195. numBytesToWrite = std::numeric_limits<int64>::max();
  196. int numWritten = 0;
  197. while (numBytesToWrite > 0)
  198. {
  199. char buffer [8192];
  200. const int num = source.read (buffer, (int) jmin (numBytesToWrite, (int64) sizeof (buffer)));
  201. if (num <= 0)
  202. break;
  203. write (buffer, num);
  204. numBytesToWrite -= num;
  205. numWritten += num;
  206. }
  207. return numWritten;
  208. }
  209. //==============================================================================
  210. void OutputStream::setNewLineString (const String& newLineString_)
  211. {
  212. newLineString = newLineString_;
  213. }
  214. //==============================================================================
  215. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number)
  216. {
  217. return stream << String (number);
  218. }
  219. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int64 number)
  220. {
  221. return stream << String (number);
  222. }
  223. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const double number)
  224. {
  225. return stream << String (number);
  226. }
  227. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char character)
  228. {
  229. stream.writeByte (character);
  230. return stream;
  231. }
  232. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char* const text)
  233. {
  234. stream.write (text, (int) strlen (text));
  235. return stream;
  236. }
  237. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& data)
  238. {
  239. if (data.getSize() > 0)
  240. stream.write (data.getData(), (int) data.getSize());
  241. return stream;
  242. }
  243. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead)
  244. {
  245. FileInputStream in (fileToRead);
  246. if (in.openedOk())
  247. return stream << in;
  248. return stream;
  249. }
  250. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, InputStream& streamToRead)
  251. {
  252. stream.writeFromInputStream (streamToRead, -1);
  253. return stream;
  254. }
  255. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&)
  256. {
  257. return stream << stream.getNewLineString();
  258. }