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.

331 lines
8.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 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. #include "../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_OutputStream.h"
  21. #include "../../threads/juce_CriticalSection.h"
  22. #include "../../containers/juce_VoidArray.h"
  23. //==============================================================================
  24. #if JUCE_DEBUG
  25. static CriticalSection activeStreamLock;
  26. static VoidArray activeStreams;
  27. void juce_CheckForDanglingStreams()
  28. {
  29. /*
  30. It's always a bad idea to leak any object, but if you're leaking output
  31. streams, then there's a good chance that you're failing to flush a file
  32. to disk properly, which could result in corrupted data and other similar
  33. nastiness..
  34. */
  35. jassert (activeStreams.size() == 0);
  36. };
  37. #endif
  38. //==============================================================================
  39. OutputStream::OutputStream() throw()
  40. {
  41. #if JUCE_DEBUG
  42. activeStreamLock.enter();
  43. activeStreams.add (this);
  44. activeStreamLock.exit();
  45. #endif
  46. }
  47. OutputStream::~OutputStream()
  48. {
  49. #if JUCE_DEBUG
  50. activeStreamLock.enter();
  51. activeStreams.removeValue (this);
  52. activeStreamLock.exit();
  53. #endif
  54. }
  55. //==============================================================================
  56. void OutputStream::writeBool (bool b)
  57. {
  58. writeByte ((b) ? (char) 1
  59. : (char) 0);
  60. }
  61. void OutputStream::writeByte (char byte)
  62. {
  63. write (&byte, 1);
  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. const int numBytes = text.copyToUTF8 (0);
  138. HeapBlock <uint8> temp (numBytes);
  139. text.copyToUTF8 (temp);
  140. write (temp, numBytes); // (numBytes includes the terminating null).
  141. }
  142. void OutputStream::printf (const char* pf, ...)
  143. {
  144. unsigned int bufSize = 256;
  145. HeapBlock <char> buf (bufSize);
  146. for (;;)
  147. {
  148. va_list list;
  149. va_start (list, pf);
  150. const int num = CharacterFunctions::vprintf (buf, bufSize, pf, list);
  151. va_end (list);
  152. if (num > 0)
  153. {
  154. write (buf, num);
  155. break;
  156. }
  157. else if (num == 0)
  158. {
  159. break;
  160. }
  161. bufSize += 256;
  162. buf.malloc (bufSize);
  163. }
  164. }
  165. OutputStream& OutputStream::operator<< (const int number)
  166. {
  167. const String s (number);
  168. write ((const char*) s, s.length());
  169. return *this;
  170. }
  171. OutputStream& OutputStream::operator<< (const double number)
  172. {
  173. const String s (number);
  174. write ((const char*) s, s.length());
  175. return *this;
  176. }
  177. OutputStream& OutputStream::operator<< (const char character)
  178. {
  179. writeByte (character);
  180. return *this;
  181. }
  182. OutputStream& OutputStream::operator<< (const char* const text)
  183. {
  184. write (text, (int) strlen (text));
  185. return *this;
  186. }
  187. OutputStream& OutputStream::operator<< (const juce_wchar* const text)
  188. {
  189. const String s (text);
  190. write ((const char*) s, s.length());
  191. return *this;
  192. }
  193. OutputStream& OutputStream::operator<< (const String& text)
  194. {
  195. write ((const char*) text,
  196. text.length());
  197. return *this;
  198. }
  199. void OutputStream::writeText (const String& text,
  200. const bool asUnicode,
  201. const bool writeUnicodeHeaderBytes)
  202. {
  203. if (asUnicode)
  204. {
  205. if (writeUnicodeHeaderBytes)
  206. write ("\x0ff\x0fe", 2);
  207. const juce_wchar* src = (const juce_wchar*) text;
  208. bool lastCharWasReturn = false;
  209. while (*src != 0)
  210. {
  211. if (*src == L'\n' && ! lastCharWasReturn)
  212. writeShort ((short) L'\r');
  213. lastCharWasReturn = (*src == L'\r');
  214. writeShort ((short) *src++);
  215. }
  216. }
  217. else
  218. {
  219. const char* src = (const char*) text;
  220. const char* t = src;
  221. for (;;)
  222. {
  223. if (*t == '\n')
  224. {
  225. if (t > src)
  226. write (src, (int) (t - src));
  227. write ("\r\n", 2);
  228. src = t + 1;
  229. }
  230. else if (*t == '\r')
  231. {
  232. if (t[1] == '\n')
  233. ++t;
  234. }
  235. else if (*t == 0)
  236. {
  237. if (t > src)
  238. write (src, (int) (t - src));
  239. break;
  240. }
  241. ++t;
  242. }
  243. }
  244. }
  245. int OutputStream::writeFromInputStream (InputStream& source,
  246. int numBytesToWrite)
  247. {
  248. if (numBytesToWrite < 0)
  249. numBytesToWrite = 0x7fffffff;
  250. int numWritten = 0;
  251. while (numBytesToWrite > 0 && ! source.isExhausted())
  252. {
  253. char buffer [8192];
  254. const int num = source.read (buffer, jmin (numBytesToWrite, sizeof (buffer)));
  255. if (num == 0)
  256. break;
  257. write (buffer, num);
  258. numBytesToWrite -= num;
  259. numWritten += num;
  260. }
  261. return numWritten;
  262. }
  263. END_JUCE_NAMESPACE