[med-svn] [htqc] 01/02: Imported Upstream version 1.92.1
Andreas Tille
tille at debian.org
Mon Jun 22 12:47:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository htqc.
commit a7a13894f85680a5446880bafd8d6636eddd9d17
Author: Andreas Tille <tille at debian.org>
Date: Mon Jun 22 14:33:33 2015 +0200
Imported Upstream version 1.92.1
---
CMakeLists.txt | 57 +
Changes.md | 597 +++++
FindHTIO2.cmake | 39 +
INSTALL.md | 59 +
README-convert.md | 63 +
README-demul.md | 38 +
README-filter.md | 26 +
README-htio.md | 124 +
README-lane-tile.md | 34 +
README-overlap.md | 38 +
README-primer-trim.md | 80 +
README-rename.md | 22 +
README-sample.md | 30 +
README-stat.md | 35 +
README-trim.md | 29 +
README.md | 151 ++
src/CMakeLists.txt | 101 +
src/ht2-convert.cpp | 238 ++
src/ht2-demul.cpp | 438 ++++
src/ht2-filter.cpp | 340 +++
src/ht2-lane-tile.cpp | 163 ++
src/ht2-overlap.cpp | 255 ++
src/ht2-primer-trim.cpp | 690 ++++++
src/ht2-rename.cpp | 114 +
src/ht2-sample.cpp | 404 ++++
src/ht2-stat-draw.pl | 520 ++++
src/ht2-stat.cpp | 759 ++++++
src/ht2-trim.cpp | 280 +++
src/ht_config.h.in | 8 +
src/htio2/Cast.cpp | 353 +++
src/htio2/Cast.h | 103 +
src/htio2/Enum.cpp | 12 +
src/htio2/Enum.h | 58 +
src/htio2/Error.cpp | 71 +
src/htio2/Error.h | 63 +
src/htio2/FastaIO.cpp | 177 ++
src/htio2/FastaIO.h | 104 +
src/htio2/FastqIO.cpp | 126 +
src/htio2/FastqIO.h | 95 +
src/htio2/FastqSeq.cpp | 42 +
src/htio2/FastqSeq.h | 66 +
src/htio2/FileHandle.cpp | 30 +
src/htio2/FileHandle.h | 94 +
src/htio2/FormatUtil.cpp | 75 +
src/htio2/FormatUtil.h | 22 +
src/htio2/GzipFileHandle.cpp | 112 +
src/htio2/GzipFileHandle.h | 88 +
src/htio2/HeaderUtil.cpp | 216 ++
src/htio2/HeaderUtil.h | 72 +
src/htio2/JUCE-3.0.8/AppConfig.h | 51 +
src/htio2/JUCE-3.0.8/CMakeLists.txt | 0
src/htio2/JUCE-3.0.8/JuceHeader.h | 19 +
src/htio2/JUCE-3.0.8/ReadMe.txt | 12 +
.../juce_core/containers/juce_AbstractFifo.cpp | 235 ++
.../juce_core/containers/juce_AbstractFifo.h | 220 ++
.../modules/juce_core/containers/juce_Array.h | 1113 +++++++++
.../containers/juce_ArrayAllocationBase.h | 138 ++
.../juce_core/containers/juce_DynamicObject.cpp | 133 +
.../juce_core/containers/juce_DynamicObject.h | 139 ++
.../juce_core/containers/juce_ElementComparator.h | 195 ++
.../modules/juce_core/containers/juce_HashMap.h | 455 ++++
.../juce_core/containers/juce_LinkedListPointer.h | 371 +++
.../juce_core/containers/juce_NamedValueSet.cpp | 271 +++
.../juce_core/containers/juce_NamedValueSet.h | 145 ++
.../modules/juce_core/containers/juce_OwnedArray.h | 897 +++++++
.../juce_core/containers/juce_PropertySet.cpp | 219 ++
.../juce_core/containers/juce_PropertySet.h | 211 ++
.../containers/juce_ReferenceCountedArray.h | 897 +++++++
.../juce_core/containers/juce_ScopedValueSetter.h | 100 +
.../modules/juce_core/containers/juce_SortedSet.h | 494 ++++
.../modules/juce_core/containers/juce_SparseSet.h | 298 +++
.../modules/juce_core/containers/juce_Variant.cpp | 780 ++++++
.../modules/juce_core/containers/juce_Variant.h | 327 +++
.../juce_core/files/juce_DirectoryIterator.cpp | 159 ++
.../juce_core/files/juce_DirectoryIterator.h | 159 ++
.../modules/juce_core/files/juce_File.cpp | 1086 +++++++++
.../JUCE-3.0.8/modules/juce_core/files/juce_File.h | 973 ++++++++
.../modules/juce_core/files/juce_FileFilter.cpp | 41 +
.../modules/juce_core/files/juce_FileFilter.h | 77 +
.../juce_core/files/juce_FileInputStream.cpp | 84 +
.../modules/juce_core/files/juce_FileInputStream.h | 96 +
.../juce_core/files/juce_FileOutputStream.cpp | 134 ++
.../juce_core/files/juce_FileOutputStream.h | 116 +
.../juce_core/files/juce_FileSearchPath.cpp | 172 ++
.../modules/juce_core/files/juce_FileSearchPath.h | 165 ++
.../juce_core/files/juce_MemoryMappedFile.h | 115 +
.../modules/juce_core/files/juce_TemporaryFile.cpp | 117 +
.../modules/juce_core/files/juce_TemporaryFile.h | 169 ++
.../juce_core/files/juce_WildcardFileFilter.cpp | 77 +
.../juce_core/files/juce_WildcardFileFilter.h | 86 +
.../modules/juce_core/javascript/juce_JSON.cpp | 643 +++++
.../modules/juce_core/javascript/juce_JSON.h | 136 ++
.../juce_core/javascript/juce_Javascript.cpp | 1710 +++++++++++++
.../modules/juce_core/javascript/juce_Javascript.h | 105 +
.../JUCE-3.0.8/modules/juce_core/juce_core.cpp | 226 ++
src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.h | 286 +++
.../JUCE-3.0.8/modules/juce_core/juce_core.mm | 29 +
.../JUCE-3.0.8/modules/juce_core/juce_module_info | 38 +
.../modules/juce_core/logging/juce_FileLogger.cpp | 134 ++
.../modules/juce_core/logging/juce_FileLogger.h | 135 ++
.../modules/juce_core/logging/juce_Logger.cpp | 63 +
.../modules/juce_core/logging/juce_Logger.h | 97 +
.../modules/juce_core/maths/juce_BigInteger.cpp | 1014 ++++++++
.../modules/juce_core/maths/juce_BigInteger.h | 334 +++
.../modules/juce_core/maths/juce_Expression.cpp | 1183 +++++++++
.../modules/juce_core/maths/juce_Expression.h | 270 +++
.../modules/juce_core/maths/juce_MathsFunctions.h | 549 +++++
.../modules/juce_core/maths/juce_Random.cpp | 189 ++
.../modules/juce_core/maths/juce_Random.h | 143 ++
.../modules/juce_core/maths/juce_Range.h | 304 +++
.../modules/juce_core/memory/juce_Atomic.h | 399 +++
.../modules/juce_core/memory/juce_ByteOrder.h | 196 ++
.../juce_core/memory/juce_ContainerDeletePolicy.h | 53 +
.../modules/juce_core/memory/juce_HeapBlock.h | 308 +++
.../juce_core/memory/juce_LeakedObjectDetector.h | 146 ++
.../modules/juce_core/memory/juce_Memory.h | 126 +
.../modules/juce_core/memory/juce_MemoryBlock.cpp | 416 ++++
.../modules/juce_core/memory/juce_MemoryBlock.h | 253 ++
.../juce_core/memory/juce_OptionalScopedPointer.h | 186 ++
.../juce_core/memory/juce_ReferenceCountedObject.h | 415 ++++
.../modules/juce_core/memory/juce_ScopedPointer.h | 253 ++
.../juce_core/memory/juce_SharedResourcePointer.h | 152 ++
.../modules/juce_core/memory/juce_Singleton.h | 292 +++
.../modules/juce_core/memory/juce_WeakReference.h | 212 ++
.../modules/juce_core/misc/juce_Result.cpp | 83 +
.../modules/juce_core/misc/juce_Result.h | 125 +
.../modules/juce_core/misc/juce_Uuid.cpp | 117 +
.../JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.h | 121 +
.../modules/juce_core/misc/juce_WindowsRegistry.h | 141 ++
.../juce_core/native/java/JuceAppActivity.java | 746 ++++++
.../juce_core/native/juce_BasicNativeHeaders.h | 223 ++
.../juce_core/native/juce_android_Files.cpp | 104 +
.../juce_core/native/juce_android_JNIHelpers.h | 428 ++++
.../modules/juce_core/native/juce_android_Misc.cpp | 32 +
.../juce_core/native/juce_android_Network.cpp | 181 ++
.../juce_core/native/juce_android_SystemStats.cpp | 315 +++
.../juce_core/native/juce_android_Threads.cpp | 76 +
.../juce_core/native/juce_linux_CommonFile.cpp | 153 ++
.../modules/juce_core/native/juce_linux_Files.cpp | 241 ++
.../juce_core/native/juce_linux_Network.cpp | 444 ++++
.../juce_core/native/juce_linux_SystemStats.cpp | 191 ++
.../juce_core/native/juce_linux_Threads.cpp | 90 +
.../modules/juce_core/native/juce_mac_Files.mm | 498 ++++
.../modules/juce_core/native/juce_mac_Network.mm | 445 ++++
.../modules/juce_core/native/juce_mac_Strings.mm | 96 +
.../juce_core/native/juce_mac_SystemStats.mm | 306 +++
.../modules/juce_core/native/juce_mac_Threads.mm | 97 +
.../juce_core/native/juce_osx_ObjCHelpers.h | 169 ++
.../juce_core/native/juce_posix_NamedPipe.cpp | 224 ++
.../juce_core/native/juce_posix_SharedCode.h | 1301 ++++++++++
.../juce_core/native/juce_win32_ComSmartPtr.h | 170 ++
.../modules/juce_core/native/juce_win32_Files.cpp | 999 ++++++++
.../juce_core/native/juce_win32_Network.cpp | 486 ++++
.../juce_core/native/juce_win32_Registry.cpp | 227 ++
.../juce_core/native/juce_win32_SystemStats.cpp | 459 ++++
.../juce_core/native/juce_win32_Threads.cpp | 625 +++++
.../modules/juce_core/network/juce_IPAddress.cpp | 149 ++
.../modules/juce_core/network/juce_IPAddress.h | 82 +
.../modules/juce_core/network/juce_MACAddress.cpp | 78 +
.../modules/juce_core/network/juce_MACAddress.h | 82 +
.../modules/juce_core/network/juce_NamedPipe.cpp | 66 +
.../modules/juce_core/network/juce_NamedPipe.h | 104 +
.../modules/juce_core/network/juce_Socket.cpp | 593 +++++
.../modules/juce_core/network/juce_Socket.h | 305 +++
.../modules/juce_core/network/juce_URL.cpp | 497 ++++
.../modules/juce_core/network/juce_URL.h | 375 +++
.../juce_core/streams/juce_BufferedInputStream.cpp | 198 ++
.../juce_core/streams/juce_BufferedInputStream.h | 92 +
.../juce_core/streams/juce_FileInputSource.cpp | 56 +
.../juce_core/streams/juce_FileInputSource.h | 66 +
.../modules/juce_core/streams/juce_InputSource.h | 78 +
.../modules/juce_core/streams/juce_InputStream.cpp | 236 ++
.../modules/juce_core/streams/juce_InputStream.h | 266 ++
.../juce_core/streams/juce_MemoryInputStream.cpp | 159 ++
.../juce_core/streams/juce_MemoryInputStream.h | 97 +
.../juce_core/streams/juce_MemoryOutputStream.cpp | 214 ++
.../juce_core/streams/juce_MemoryOutputStream.h | 139 ++
.../juce_core/streams/juce_OutputStream.cpp | 351 +++
.../modules/juce_core/streams/juce_OutputStream.h | 278 +++
.../juce_core/streams/juce_SubregionStream.cpp | 82 +
.../juce_core/streams/juce_SubregionStream.h | 88 +
.../modules/juce_core/system/juce_PlatformDefs.h | 388 +++
.../modules/juce_core/system/juce_StandardHeader.h | 157 ++
.../modules/juce_core/system/juce_SystemStats.cpp | 183 ++
.../modules/juce_core/system/juce_SystemStats.h | 195 ++
.../modules/juce_core/system/juce_TargetPlatform.h | 201 ++
.../juce_core/text/juce_CharPointer_ASCII.h | 387 +++
.../juce_core/text/juce_CharPointer_UTF16.h | 525 ++++
.../juce_core/text/juce_CharPointer_UTF32.h | 378 +++
.../modules/juce_core/text/juce_CharPointer_UTF8.h | 572 +++++
.../juce_core/text/juce_CharacterFunctions.cpp | 154 ++
.../juce_core/text/juce_CharacterFunctions.h | 629 +++++
.../modules/juce_core/text/juce_Identifier.cpp | 70 +
.../modules/juce_core/text/juce_Identifier.h | 120 +
.../juce_core/text/juce_LocalisedStrings.cpp | 209 ++
.../modules/juce_core/text/juce_LocalisedStrings.h | 247 ++
.../modules/juce_core/text/juce_NewLine.h | 86 +
.../modules/juce_core/text/juce_String.cpp | 2543 ++++++++++++++++++++
.../modules/juce_core/text/juce_String.h | 1370 +++++++++++
.../modules/juce_core/text/juce_StringArray.cpp | 485 ++++
.../modules/juce_core/text/juce_StringArray.h | 421 ++++
.../juce_core/text/juce_StringPairArray.cpp | 147 ++
.../modules/juce_core/text/juce_StringPairArray.h | 157 ++
.../modules/juce_core/text/juce_StringPool.cpp | 166 ++
.../modules/juce_core/text/juce_StringPool.h | 94 +
.../modules/juce_core/text/juce_StringRef.h | 138 ++
.../modules/juce_core/text/juce_TextDiff.cpp | 247 ++
.../modules/juce_core/text/juce_TextDiff.h | 80 +
.../juce_core/threads/juce_ChildProcess.cpp | 113 +
.../modules/juce_core/threads/juce_ChildProcess.h | 119 +
.../juce_core/threads/juce_CriticalSection.h | 266 ++
.../juce_core/threads/juce_DynamicLibrary.h | 85 +
.../juce_core/threads/juce_HighResolutionTimer.cpp | 36 +
.../juce_core/threads/juce_HighResolutionTimer.h | 109 +
.../juce_core/threads/juce_InterProcessLock.h | 128 +
.../modules/juce_core/threads/juce_Process.h | 153 ++
.../juce_core/threads/juce_ReadWriteLock.cpp | 150 ++
.../modules/juce_core/threads/juce_ReadWriteLock.h | 152 ++
.../modules/juce_core/threads/juce_ScopedLock.h | 237 ++
.../juce_core/threads/juce_ScopedReadLock.h | 90 +
.../juce_core/threads/juce_ScopedWriteLock.h | 90 +
.../modules/juce_core/threads/juce_SpinLock.h | 91 +
.../modules/juce_core/threads/juce_Thread.cpp | 371 +++
.../modules/juce_core/threads/juce_Thread.h | 289 +++
.../juce_core/threads/juce_ThreadLocalValue.h | 198 ++
.../modules/juce_core/threads/juce_ThreadPool.cpp | 384 +++
.../modules/juce_core/threads/juce_ThreadPool.h | 321 +++
.../juce_core/threads/juce_TimeSliceThread.cpp | 171 ++
.../juce_core/threads/juce_TimeSliceThread.h | 149 ++
.../modules/juce_core/threads/juce_WaitableEvent.h | 118 +
.../juce_core/time/juce_PerformanceCounter.cpp | 132 +
.../juce_core/time/juce_PerformanceCounter.h | 127 +
.../modules/juce_core/time/juce_RelativeTime.cpp | 139 ++
.../modules/juce_core/time/juce_RelativeTime.h | 184 ++
.../modules/juce_core/time/juce_Time.cpp | 469 ++++
.../JUCE-3.0.8/modules/juce_core/time/juce_Time.h | 404 ++++
.../modules/juce_core/unit_tests/juce_UnitTest.cpp | 260 ++
.../modules/juce_core/unit_tests/juce_UnitTest.h | 311 +++
.../modules/juce_core/xml/juce_XmlDocument.cpp | 891 +++++++
.../modules/juce_core/xml/juce_XmlDocument.h | 181 ++
.../modules/juce_core/xml/juce_XmlElement.cpp | 888 +++++++
.../modules/juce_core/xml/juce_XmlElement.h | 763 ++++++
.../zip/juce_GZIPCompressorOutputStream.cpp | 213 ++
.../zip/juce_GZIPCompressorOutputStream.h | 101 +
.../zip/juce_GZIPDecompressorInputStream.cpp | 288 +++
.../zip/juce_GZIPDecompressorInputStream.h | 97 +
.../modules/juce_core/zip/juce_ZipFile.cpp | 608 +++++
.../modules/juce_core/zip/juce_ZipFile.h | 259 ++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/README | 125 +
.../modules/juce_core/zip/zlib/adler32.c | 143 ++
.../modules/juce_core/zip/zlib/compress.c | 70 +
.../JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.c | 407 ++++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.h | 441 ++++
.../modules/juce_core/zip/zlib/deflate.c | 1679 +++++++++++++
.../modules/juce_core/zip/zlib/deflate.h | 333 +++
.../modules/juce_core/zip/zlib/infback.c | 611 +++++
.../modules/juce_core/zip/zlib/inffast.c | 316 +++
.../modules/juce_core/zip/zlib/inffast.h | 11 +
.../modules/juce_core/zip/zlib/inffixed.h | 94 +
.../modules/juce_core/zip/zlib/inflate.c | 1339 +++++++++++
.../modules/juce_core/zip/zlib/inflate.h | 121 +
.../modules/juce_core/zip/zlib/inftrees.c | 328 +++
.../modules/juce_core/zip/zlib/inftrees.h | 61 +
.../JUCE-3.0.8/modules/juce_core/zip/zlib/trees.c | 1191 +++++++++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/trees.h | 127 +
.../modules/juce_core/zip/zlib/uncompr.c | 60 +
.../JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.h | 345 +++
.../modules/juce_core/zip/zlib/zconf.in.h | 332 +++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/zlib.h | 1358 +++++++++++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.c | 311 +++
.../JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.h | 271 +++
src/htio2/Kmer.cpp | 436 ++++
src/htio2/Kmer.h | 553 +++++
src/htio2/MT19937.cpp | 270 +++
src/htio2/MT19937.h | 97 +
src/htio2/OptionParser.cpp | 609 +++++
src/htio2/OptionParser.h | 231 ++
src/htio2/PairedEndIO.cpp | 206 ++
src/htio2/PairedEndIO.h | 133 +
src/htio2/PlainFileHandle.cpp | 117 +
src/htio2/PlainFileHandle.h | 86 +
src/htio2/QualityUtil.cpp | 149 ++
src/htio2/QualityUtil.h | 150 ++
src/htio2/RefCounted.cpp | 12 +
src/htio2/RefCounted.h | 156 ++
src/htio2/RingBuffer.h | 95 +
src/htio2/SeqIO.cpp | 99 +
src/htio2/SeqIO.h | 139 ++
src/htio2/SimpleSeq.cpp | 89 +
src/htio2/SimpleSeq.h | 87 +
src/htio2/StringUtil.cpp | 34 +
src/htio2/StringUtil.h | 55 +
src/htio2/Version.cpp | 18 +
src/htio2/Version.h | 18 +
src/htio2/config.h.in | 8 +
src/htqc/App.cpp | 41 +
src/htqc/App.h | 14 +
src/htqc/BaseQualCounter.cpp | 112 +
src/htqc/BaseQualCounter.h | 112 +
src/htqc/Common.cpp | 96 +
src/htqc/Common.h | 63 +
src/htqc/FastqStat.cpp | 184 ++
src/htqc/FastqStat.h | 63 +
src/htqc/MicroAssembler.cpp | 289 +++
src/htqc/MicroAssembler.h | 63 +
src/htqc/MultiSeqFile.cpp | 122 +
src/htqc/MultiSeqFile.h | 75 +
src/htqc/Options.cpp | 337 +++
src/htqc/Options.h | 121 +
src/htqc/Primer.cpp | 127 +
src/htqc/Primer.h | 47 +
t/CMakeLists.txt | 275 +++
t/TestConfig.h.in | 6 +
t/TestFramework.cpp | 164 ++
t/TestFramework.h | 155 ++
t/barcodes.tab | 66 +
t/double_1.fastq | 8 +
t/double_2.fastq | 8 +
t/double_ovlp.fastq | Bin 0 -> 787 bytes
t/filt.fastq.gz | Bin 0 -> 14014 bytes
t/filt_1.fastq.gz | Bin 0 -> 6195 bytes
t/filt_2.fastq.gz | Bin 0 -> 6375 bytes
t/filt_fail.fastq.gz | Bin 0 -> 8023 bytes
t/filt_fail_1.fastq.gz | Bin 0 -> 3168 bytes
t/filt_fail_2.fastq.gz | Bin 0 -> 3110 bytes
t/filt_fail_s.fastq.gz | Bin 0 -> 2292 bytes
t/filt_s.fastq.gz | Bin 0 -> 2140 bytes
t/option_parser.cpp | 54 +
t/primers.fasta | 13 +
t/single_1.fastq | 4 +
t/single_2.fastq | 4 +
t/t_cast.cpp | 80 +
t/t_fasta_io.cpp | 72 +
t/t_fastq_io.cpp | 72 +
t/t_gzip_file_handle.cpp | 56 +
t/t_header_util.cpp | 37 +
t/t_ht_convert.cpp | 17 +
t/t_ht_demul.cpp | 126 +
t/t_ht_filter.cpp | 101 +
t/t_ht_lane_tile.cpp | 38 +
t/t_ht_overlap.cpp | 11 +
t/t_ht_rename.cpp | 37 +
t/t_ht_sample.cpp | 81 +
t/t_ht_trim.cpp | 24 +
t/t_kmer_aa.cpp | 60 +
t/t_kmer_nt4_16.cpp | 96 +
t/t_kmer_nt4_32.cpp | 109 +
t/t_kmer_nt4_64.cpp | 173 ++
t/t_kmer_nt5_16.cpp | 96 +
t/t_kmer_nt5_32.cpp | 100 +
t/t_kmer_nt5_64.cpp | 162 ++
t/t_mt19937.cpp | 167 ++
t/t_multi_seq_file_pe.cpp | 141 ++
t/t_multi_seq_file_se.cpp | 52 +
t/t_plain_file_handle.cpp | 64 +
t/t_ref_counted.cpp | 42 +
t/t_ring_buffer.cpp | 67 +
t/t_simple_seq.cpp | 49 +
t/t_string.cpp | 58 +
t/t_text_file_equal.cpp | 14 +
t/test1.fasta | 400 +++
t/test1.fastq | 400 +++
t/test1.fastq.gz | Bin 0 -> 10941 bytes
t/test2.fasta | 400 +++
t/test2.fastq | 400 +++
t/test2.fastq.gz | Bin 0 -> 10969 bytes
t/test_interleave.fastq.gz | Bin 0 -> 21549 bytes
t/test_novlp_1.fastq.gz | Bin 0 -> 2694 bytes
t/test_novlp_2.fastq.gz | Bin 0 -> 2829 bytes
t/test_ovlp.fastq.gz | Bin 0 -> 11933 bytes
t/trim_1.fastq.gz | Bin 0 -> 10733 bytes
t/trim_2.fastq.gz | Bin 0 -> 10768 bytes
t/trim_both.fastq.gz | Bin 0 -> 10733 bytes
t/trim_head.fastq.gz | Bin 0 -> 10874 bytes
t/trim_tail.fastq.gz | Bin 0 -> 10812 bytes
375 files changed, 85726 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..73d0f1a
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,57 @@
+# HTQC - a high-throughput sequencing quality control toolkit
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 2.8)
+project(htqc)
+
+if (CMAKE_BUILD_TYPE STREQUAL "")
+ # CMake defaults to leaving CMAKE_BUILD_TYPE empty. This screws up
+ # differentiation between debug and release builds.
+ set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: None (CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif ()
+
+list(APPEND CMAKE_CXX_FLAGS "-std=c++11")
+#set(CMAKE_EXE_LINKER_FLAGS_DEBUG ${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fsanitize=address)
+
+set(CPACK_PACKAGE_VERSION_MAJOR 1)
+set(CPACK_PACKAGE_VERSION_MINOR 92)
+set(CPACK_PACKAGE_VERSION_PATCH 1)
+set(CPACK_GENERATOR TGZ)
+set(CPACK_SOURCE_GENERATOR TGZ)
+set(CPACK_SOURCE_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES} ".kdev4" "~" "build" "nbproject" "test_data" "CMakeLists.txt.user*")
+
+include(CPack)
+
+find_package(ZLIB)
+message(STATUS " Zlib inc dir : ${ZLIB_INCLUDE_DIRS}")
+message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}")
+
+include(GNUInstallDirs)
+message(STATUS "GNU install dirs")
+message(STATUS " bin: ${CMAKE_INSTALL_BINDIR}")
+message(STATUS " lib: ${CMAKE_INSTALL_LIBDIR}")
+message(STATUS " inc: ${CMAKE_INSTALL_INCLUDEDIR}")
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_BINARY_DIR}/src
+ ${ZLIB_INCLUDE_DIRS}
+)
+
+set(juce_dep_libs pthread rt dl)
+
+add_subdirectory(src)
+add_subdirectory(t)
diff --git a/Changes.md b/Changes.md
new file mode 100644
index 0000000..49aa0bc
--- /dev/null
+++ b/Changes.md
@@ -0,0 +1,597 @@
+Changes
+=======
+
+1.92.1
+======
+
+ - ht2-overlap:
+
+ Fixed a severe bug that overlapping part in result sequence all come from
+ read 1, and probably using incorrect position.
+
+1.92.0
+======
+
+ - Use *JUCE* library to provide utility functions, and removed dependency on
+ *boost* whose CMake finder module is problematic. The *JUCE* stuffs are put
+ inside `htio2::juce` namespace.
+
+ - htio2 library
+
+ Added string manipulation functions in `StringUtil.h`: `split`, `join`,
+ `to_upper_case` and `to_lower_case`.
+
+ Added a command line option parser facility in `OptionParser.h`.
+
+ Replaced boost::intrusive_ptr by self-written pointer type. The Smart
+ pointer types for each class is defined inside the class. For example,
+ `FooBarPtr` are redefined to `FooBar::Ptr`.
+
+ Removed dependency on regular expression engine. Header format is guessed
+ using manually-written parser.
+
+ Modify the prefix of header file guardian macros from `HTIO_` to `HTIO2_`.
+
+ - all programs
+
+ Using `htio2::OptionParser` to parse command line options, which replaces
+ `boost::program_options`. Some option names are slightly modified.
+
+ Set default quality encoding from casava1.8 to unknown, which let the
+ program to guess sequence quality encoding.
+
+ - ht2-demul
+
+ Fixed a severe bug that when working with paired-end reads, read 1 is
+ written to both output.
+
+ Added unit test for read end validation.
+
+ - ht-stat
+
+ Fixed a bug that when working with very few amount of paired-end reads, the
+ QQ plot sampling would fall into endless cycle.
+
+ Use lock-free ring buffers to pass information between threads.
+
+ - ht2-sample
+
+ Now get accurate amount of results, instead of approximate amount.
+
+ Can directly specify number, or specify fraction of total.
+
+ Can write the indices of selected reads (or read pairs) into a file.
+
+1.91.0
+======
+ - use GNUInstallDirs to provide correct install location.
+
+ - finished ht2-filter and ht2-lane-tile.
+
+ - use markdown format for all documents.
+
+1.90.1
+======
+
+ - all programs:
+
+ The "--gzip/-z" option no longer exists. Compression is deduced by input
+ file name.
+
+ - ht2-filter and ht2-lane-tile-pick
+
+ Filter by length and quality at one time: pick those sequence whose length
+ of high quality bases is longer than length cutoff. The function of tile
+ filter is separated to ht2-lane-tile-pick.
+
+1.90.0
+======
+
+This is the pre-release of version 2.
+
+ - htio library
+
+ Header files are placed in htio2/ directory.
+
+ Added a new "RefCounted" base class which provides refcount. All
+ refcounted classes use Boost's intrusive_ptr class to provide a default
+ implementation for smart pointer.
+
+ Added a new "PairedEndIO" class which read/write paired-end reads, and
+ process issues such as interleaved / reverted mate pairs.
+
+ Moved all sequence format utilities into "SeqFormat.h", and added
+ functions to guess sequence format by file name or content.
+
+ Added write_seq(const FastqSeq&) to SeqIO base class.
+
+ Removed "HTIO_" prefix from all enums.
+
+ Tidy header file inclusion to increase compile speed.
+
+ Kmer utilities now support different memory size of Kmer type via template
+ specialization. Default specializations includes 64, 32 and 16 bit unsigned
+ integers.
+
+ Fixed errors of seek with SEEK_CUR and SEEK_END for the file handle classes.
+
+ - all programs
+
+ Allow interleaved input/output for paired-end reads.
+
+ Use output file prefix instead of file name, so that all programs have same
+ behaviour.
+
+ - ht2-convert
+
+ a new program that converts sequence format, quality encoding, etc..
+
+ - ht2-overlap
+
+ the previous ht-asm program renamed to ht2-overlap to clarify its function.
+
+ - ht2-primer-trim
+
+ Supports multiple output by different primer set.
+
+ Do check reverse-complement strand by default, and use "--no-revcom" option
+ to disable this behaviour.
+
+ Added "--no-trim" option to not trim the primer sequence from reads, and
+ only pick the primer-containing reads.
+
+0.90.8
+======
+
+ - ht-demul
+
+ ".gz" suffix will be added for gzipped output files.
+
+0.90.7
+======
+
+ - ht-qual-recode
+
+ a new program for changing the encoding of sequence quality.
+
+ - GZipFileHandle.h and SeqIO.h
+
+ fixed an error that may cause conflicting type declaration of "gzFile", on
+ some version of zlib.
+
+0.90.6
+======
+
+ - ht-demul
+
+ fixed a bug that the program crashes if the output directory is not exist.
+
+ fixed a bug that the barcode file is not properly parsed.
+
+ - htio library
+
+ documentation for all functions.
+
+ FindHTIO1.cmake.
+
+ README_htio for simple tutorial on htio library.
+
+ two new functions for kmer generation. The length of whole input string is
+ treated as kmer size.
+
+0.90.5
+======
+
+ - htio library
+
+ removed #include in header files as much as possible. This would help to
+ increase compile speed.
+
+ - improved quality encode guessing strategy.
+
+ - guess encoding and header format from front 500 sequences.
+
+0.90.4
+======
+
+ - ht-primer-trim
+
+ changed default cutoff for allowed tail missing from 3 to 5.
+
+ - ht-asm
+
+ fixed an error which would cause segfault on specific inputs.
+
+ - added README for each program.
+
+ - source code
+
+ moved all C++ sources into a subdirectory so that the main directory would
+ have a clean look.
+
+0.90.3
+======
+
+ - htio library
+
+ fixed an bug on tell() of PlainFileHandle and GzipFileHandle.
+
+ fixed an bug on EncodedSeq revcom.
+
+ allowing FastaIO to read and write FastqSeq.
+
+0.90.2
+======
+
+ - htio library
+
+ added functions htio::SeqIO::New(), that automatically guess sequence format
+ from file content, and create handle for it.
+
+ fixed an error on FileHandle that seek() will disturb the file offset.
+
+ fixed an error on FastaIO that seek() will disturb the file offset. Now it
+ is ensured after reading one sequence, the offset is at the start of the
+ next sequence's header line.
+
+0.90.1
+======
+
+ - htio library
+
+ added operators on EncodedSeq and KmerList.
+
+ - fixed a bug that ht-primer-trim won't be installed.
+
+0.90.0
+======
+
+ - htio library
+
+ the include directory and library name now renamed to "htio1", with revised
+ API and ABI.
+
+ add functions for guess quality encoding and header format.
+
+ headers will be installed to PREFIX/include/htio1, and library is renamed to
+ libhtio1
+
+ quality range of CASAVA_1_8 changed to 0 - 41.
+
+ line reader can recognize CR, LF and CRLF.
+
+ - all programs
+
+ automatically guess quality encoding and header format.
+
+ - ht-asm
+
+ the old "ht-join" program now renamed to "ht-asm".
+
+ - ht-demul
+
+ a new program to demultiplex reads by barcode. Barcodes are got from the
+ FASTQ header.
+
+ - ht-primer-trim
+
+ a new program to remove primer sequence from reads.
+
+ - ht-stat
+
+ fixed a bug that the program crashes when the number of threads is more than
+ the number of input sequences.
+
+ - ht-stat-draw.pl
+
+ refined the output of lane-tile plots.
+
+ as GNUplot has issues on SVG heatmap, change default output format to PNG.
+
+ removed default font face setting from 'Arial' to '*', in avoid that some
+ machines don't have that font.
+
+0.15.1
+======
+
+ - revised CMakeLists.txt
+
+ might fix some bugs caused by library locating.
+
+ - ht-rename
+
+ by default, don't keep reads description (contents after first continuous
+ blank).
+
+0.15.0
+======
+
+ - all programs
+
+ use Boost instead of Glib.
+
+ - ht-rename
+
+ a new program to generate simple sequence IDs by batch.
+
+ - ht-stat
+
+ don't need to specify maximum read length.
+
+ - ht-filter
+
+ now won't accept zero-length sequences when filtering by quality.
+
+0.14.1
+======
+
+ - ht-stat
+
+ fixed a severe error that the program stucks at the third input file, due to
+ inappropriate queue access.
+
+0.14.0
+======
+
+ - ht-trim
+
+ require several continuous residues of good quality. If you want to fall
+ back to old behavior, set word size to 1.
+
+ - all programs
+
+ show help when run without any parameters.
+
+ check suffix for output file names and prefixes.
+
+0.13.2
+======
+
+ - all programs
+
+ add ".gz" suffix for output file names when using gzipped input and output.
+
+ user must specify "--single" or "--paired" explicitly, instead of single
+ mode by default.
+
+ - ht-join
+
+ specify output prefix for unjoined sequences using one single option "-u".
+
+0.13.1
+======
+
+ - HTIO library
+
+ fixed an error in FastqIO, that the program aborts when sequence has ID only
+ and has no description.
+
+ - added unit tests.
+
+ - README and program help
+
+ corrected some disaccording descriptions due to the upgrade from 0.12.X to
+ 0.13.X.
+
+0.13.0
+======
+
+ - HTIO library
+
+ major API change.
+
+ added documentation.
+
+ - ht-stat
+
+ fixed a severe error that if multiple input files are given, the program
+ halts after finishing the first file.
+
+ - ht-filter
+
+ combines ht_length_filter, ht_tile_filter, ht_qual_filter into one program.
+
+ - all programs
+
+ use "-" instead of "_" in program names, so all programs are named "ht-xxx"
+ instead of "ht_xxx"
+
+ use single option "-o" to specify output prefix, instead of using "-a" "-b"
+ "-s" separately.
+
+0.12.1
+======
+
+ - ht_join
+
+ write unjoined sequences to user specified files (options -U -V).
+
+0.12.0
+======
+
+ - source code
+
+ IO classes and FASTQ sequence classes are moved to a new library named HTIO.
+
+ - ht_qual_filter, ht_length_filter, ht_sample
+
+ output for single-end mode now use "--out-s" instead of "--out-a".
+
+ - ht_stat_draw.pl
+
+ help document now provides correct usage.
+
+ - added reference in README.
+
+0.11.1
+======
+
+ - ht_stat
+
+ fixed a bug that parameters are not correctly printed to info file.
+
+ - ht_join
+
+ fixed a bug that quality on assembled sequence tail was not generated
+ correctly.
+
+ write more information to output sequence header.
+
+ aligning bases must both have good quality to be considered identical. This
+ will make the alignment more stringent.
+
+ - all programs
+
+ print parameters on log.
+
+ print log on STDOUT instead of STDERR.
+
+0.11.0
+======
+
+ - ht_join
+
+ a new program that joins paired-end reads into single sequences.
+
+ - all programs
+
+ use '--quiet' instead of '--verbose'. Thus all programs will by default
+ print information, unless you explicitly let them quiet.
+
+ - source code
+
+ checked if the GPL v3 license exists in all source files.
+
+ the command line option objects that have enumerative string values now use
+ G_OPTION_ARG_CALLBACK type, so that main functions of related programs don't
+ need to parse these options by themselves.
+
+0.10.2
+======
+
+ - all programs
+
+ support read/write gzipped sequences.
+
+ exit with error message when failed to open a file.
+
+ - source code
+
+ modified file layout; move everything to "htqc" namespace.
+
+ use C style stdio to read sequences instead of C++ stream.
+
+0.10.1
+======
+
+ - ht_stat
+
+ refined thread usage.
+
+ fixed an error that the program behaved weirdly if there are too few input
+ reads.
+
+ - ht_length_filter, ht_qual_filter, ht_sample
+
+ If the program did not work in paired-end mode ("--paired" or "-p"), but
+ output files were provided for the other end ("--out-b" or "-b") or the
+ unpaired ("--out-single" or "-s"), these programs will claim that.
+
+ - all programs
+
+ common option objects are compiled into a library. This is for the ease of
+ development, and does not affect user experience.
+
+0.10.0
+======
+
+ - all programs
+
+ able to take multiple input files. Command-line options are modified
+ accordingly.
+
+ - ht_stat, ht_tile_filter
+
+ control FASTQ quality encoding and header format using separate options
+ ("--encode" and "--header-format").
+
+ - ht_stat
+
+ creates separate files for text reports instead of one big file, and "--out"
+ option now specifies an output folder containing these files.
+
+ - ht_trim
+
+ this program replaces ht_tail_filter, and it can trim reads from both head
+ and tail.
+
+ - refined README and program help.
+
+0.9.7
+=====
+
+ - ht_stat
+
+ fixed the bug when -l is longer than actual read size, -65535 was given in
+ some charts.
+
+ - added a new program named "ht_sample" to pick sample from reads.
+
+ - FASTQ parser
+
+ modified '+' line validation.
+
+0.9.6
+=====
+
+ - ht_stat
+
+ threaded
+
+ - re-organize source code
+
+ - solved warnings about const char*
+
+0.9.5
+=====
+
+ - ht_stat
+
+ calculate Pearson correlation and print in QQ plot
+
+ - ht_stat.pl
+
+ changed line color for distribution of read quality and read length.
+
+0.9.4
+=====
+
+ - ht_stat_draw.pl
+
+ allow users to select picture format
+
+ - print logs on stderr
+
+0.9.3
+=====
+
+ - in addition of cycle quality heat map, add a box graph
+
+ - correct descriptions of program helps
+
+0.9.2
+=====
+
+ - a new perl script for rendering ht_stat outputs using gnuplot
+
+ - added '-v' or '--version' command-line switch to show program version
+
+0.9.1
+=====
+
+ - filled bugs in regexp for illumina header
+
+0.9.0
+=====
+
+ - initial release
diff --git a/FindHTIO2.cmake b/FindHTIO2.cmake
new file mode 100644
index 0000000..e2b86ac
--- /dev/null
+++ b/FindHTIO2.cmake
@@ -0,0 +1,39 @@
+include(FindPackageHandleStandardArgs)
+include(GNUInstallDirs)
+
+set(HTIO2_ROOT "" CACHE PATH "Additional HTIO2 search path")
+
+# find HTIO2 config header
+find_file(htio2_config_h htio2/config.h
+ PATHS ${HTIO2_ROOT}
+ PATH_SUFFIXES ${CMAKE_INSTALL_INCLUDEDIR})
+
+#message(STATUS " config header: ${htio2_config_h}")
+
+# parse version
+if(htio2_config_h)
+ file(STRINGS ${htio2_config_h} line_major REGEX "VERSION_MAJOR")
+ file(STRINGS ${htio2_config_h} line_minor REGEX "VERSION_MINOR")
+ file(STRINGS ${htio2_config_h} line_patch REGEX "VERSION_PATCH")
+
+ string(REGEX REPLACE "^.*VERSION_MAJOR +([0-9]+).*$" "\\1" HTIO2_VERSION_MAJOR "${line_major}")
+ string(REGEX REPLACE "^.*VERSION_MINOR +([0-9]+).*$" "\\1" HTIO2_VERSION_MINOR "${line_minor}")
+ string(REGEX REPLACE "^.*VERSION_PATCH +([0-9]+).*$" "\\1" HTIO2_VERSION_PATCH "${line_patch}")
+ set(HTIO2_VERSION_STRING "${HTIO2_VERSION_MAJOR}.${HTIO2_VERSION_MINOR}.${HTIO2_VERSION_PATCH}")
+ get_filename_component(HTIO2_INCLUDE_DIRS ${htio2_config_h} PATH CACHE)
+endif()
+
+# find HTIO2 library
+find_library(htio2_archive htio2
+ PATHS ${HTIO2_ROOT}
+ PATH_SUFFIXES ${CMAKE_INSTALL_LIBDIR})
+
+if(htio2_archive)
+ set(HTIO2_LIBRARIES ${htio2_archive} CACHE STRING "HTIO2 library")
+endif()
+
+#message(STATUS " library: ${htio2_archive}")
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(HTIO2
+ REQUIRED_VARS htio2_config_h htio2_archive
+ VERSION_VAR HTIO2_VERSION_STRING)
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..034e837
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,59 @@
+HTQC installation guide
+=======================
+
+CMake
+-----
+
+HTQC uses CMake to generate platform-specific build files. You must have CMake
+to build HTQC. To test whether you have CMake on your system, run:
+ $ cmake -h
+
+It should print help information if CMake has been properly installed.
+
+If you don't have a CMake in your system, please use your Unix system's package
+management system, or download CMake from their website: http://www.cmake.org/
+
+Simple install
+--------------
+
+Goto the source code directory:
+
+ $ cd (where_you_put_the_code)/htqc-X.X.X-Source
+
+In the source code dir, create a place to conatin build results:
+
+ $ mkdir build
+ $ cd build
+
+* Now we are in (where_you_put_the_code)/htqc-X.X.X-Source/build.
+* Please make sure the file "CMakeLists.txt" exists in the upper directory of
+ "build" directory.
+
+Run cmake to generate makefile:
+
+ $ cmake ..
+
+* ".." indicates the upper directory is the root of project
+* the file "Makefile" should be generated in current directory
+
+Build and install
+
+ $ make
+ $ su
+ $ make install
+
+Customized install
+------------------
+
+If you can't get system-wide permission to copy programs to "/usr/local/bin",
+you can install the program only for yourself. To do this, run cmake by
+specifying install prefix to a directory under your control:
+
+ $ cmake -DCMAKE_INSTALL_PREFIX=~ ../
+ $ make
+ $ make install
+
+It will install the programs to "~/bin" and libraries to "~/lib", which you
+have permissions to create files.
+
+For more options, please refer to the handbook of CMake.
diff --git a/README-convert.md b/README-convert.md
new file mode 100644
index 0000000..fc9d19d
--- /dev/null
+++ b/README-convert.md
@@ -0,0 +1,63 @@
+ht2-convert - convert reads storage format
+==========================================
+
+Introduction
+------------
+
+The program `ht2-convert` can convert several aspects for FASTQ format
+sequences, including:
+
+ - quality encode
+ - paired-end interleaving
+ - strand
+
+### Paired-end Interleaving
+
+There are two common ways to store paired-end files. One way is to store them in
+separate file pairs, each containing one end:
+
+ File 1: File 2:
+ r1_1 r1_2
+ r2_1 r2_2
+ r3_1 r3_2
+
+and the other way is to store them in one file, which is called **interleaving**:
+
+ File:
+ r1_1
+ r1_2
+ r2_1
+ r2_2
+ r3_1
+ r3_2
+
+### Strand
+
+In most common cases, paired-end sequences has following layout:
+
+ >>>> read 1 >>>>
+ =========================== sequence ===========================
+ <<<< read 2 <<<<
+
+However, for long insertion size libraries, the paired-end sequences may have
+this layout:
+
+ >>>> read 1 >>>>
+ =========================== sequence ===========================
+ <<<< read 2 <<<<
+
+-----
+Usage
+-----
+
+Separate interleaved file:
+
+ $ ht2-convert -P --pe-itlv -i input.fastq -o output
+
+files "output_1.fastq" and "output_2.fastq" will be generated.
+
+Combine file pairs into interleaved file:
+
+ $ ht2-convert -P --out-pe-itlv -i input_1.fastq input_2.fastq -o output
+
+the file "output.fastq" will be generated.
diff --git a/README-demul.md b/README-demul.md
new file mode 100644
index 0000000..df4893c
--- /dev/null
+++ b/README-demul.md
@@ -0,0 +1,38 @@
+ht2-demul - separate sequences by lane ID and barcode sequence
+=============================================================
+
+Introduction
+------------
+
+Many high-throughput sequencing platforms allow multiple samples being sequenced
+together, and distinguish the samples using known short oligonucleotides
+(usually named "index" or "barcode). Therefore, it is necessary to separate
+reads from different samples after you get the raw sequencing data, and this
+operation is called **demultiplexing**.
+
+The program `ht2-demul` separates reads from different samples using barcode
+sequences stored in FASTQ header line.
+
+Input and output
+----------------
+
+The input sequences can be single-end or paired-end. The sequence header must be
+CASAVA 1.8 format, because prior to CASAVA version 1.8, the barcode
+sequence is not stored in the headers.
+
+The barcode file should be a tab-delimited plain text with 3 columns, which are:
+
+ - project name
+ - sample name
+ - barcode sequence
+
+Demultiplexed reads are firstly grouped into folders according to project name,
+then by files according to sample name, so it is better to not include spaces in
+your project name and sample name.
+
+Usage
+-----
+
+Results are written to directory "output":
+
+ $ ht2-demul --paired-end --barcode barcodes.tab -i IN_1.fastq IN_2.fastq -o output
diff --git a/README-filter.md b/README-filter.md
new file mode 100644
index 0000000..424b2a5
--- /dev/null
+++ b/README-filter.md
@@ -0,0 +1,26 @@
+ht2-filter - filter reads by different criteria
+===============================================
+
+Introduction
+------------
+
+The program `ht2-filter` filters sequences according to the length of high
+quality bases.
+
+Input and output
+----------------
+
+Both single-end and paired-end reads are accepted. When paired-end reads is
+processed, the number of input files should be even, and the files of read 1
+should be given on front, then follwing the files of read 2.
+
+When input reads are paired-end and only one end is accepted, it will be
+written to a separate file (OutputPrefix_s.fastq).
+
+Usage
+-----
+
+The accepted reads will be stored in file OUT_1.fastq and OUT_2.fastq, and the
+one-end-accepted reads will be stored in file OUT_s.fastq.
+
+ $ ht2-filter --paired-end -i IN_1.fastq IN_2.fastq -o OUT
diff --git a/README-htio.md b/README-htio.md
new file mode 100644
index 0000000..586a244
--- /dev/null
+++ b/README-htio.md
@@ -0,0 +1,124 @@
+HTIO - high-throughput sequence processing library
+==================================================
+
+Introduction
+------------
+
+HTIO is a library for processing high-throughput sequences. It contains
+functions for FASTA/FASTQ file read/write, quality score decoding, FASTQ header
+parsing, k-mer generation etc..
+
+Synopsis
+--------
+
+ #include <htio2/FastqIO.h>
+ #include <htio2/FastqSeq.h>
+ //......
+
+Usage
+-----
+
+To use HTIO library, you need to include corresponding header files in your
+source code:
+
+ #include <htio2/FastqIO.h>
+ #include <htio2/FastqSeq.h>
+ #include <htio2/Kmer.h>
+ //......
+
+To compile your program, you need to include the directory containing HTIO
+header files, and link with HTIO library:
+
+ $ g++ -o my_program -I MY/HEADER/PREFIX my_program.cpp MY/PATH/TO/libhtio2.a
+
+By default, HTIO headers are installed to `/usr/local/include`, and the static
+libraries are installed to `/usr/local/lib` (or `/usr/local/lib64` for 64-bit
+*Fedora* systems). So you probably don't need to specify the `-I` option:
+
+ $ g++ -o my_program my_program.cpp /usr/local/lib/libhtio1.a
+
+Examples
+--------
+
+Convert sequences from FASTQ to FASTA:
+
+ #include <htio1/FastqIO.h>
+ #include <htio1/FastaIO.h>
+ #include <htio1/FastqSeq.h>
+
+ int main(int argc, char** argv)
+ {
+ // create file handles
+ htio::FastqIO fh_in(argv[1], htio::HTIO_READ);
+ htio::FastaIO fh_out(argv[2], htio::HTIO_WRITE);
+
+ // read and write sequences
+ htio::FastqSeq seq;
+ while (fh_in.next_seq(seq))
+ fh_out.write_seq(seq);
+ }
+
+Show positions where qualitiy is lower than 20:
+
+ #include <htio1/FastqIO.h>
+ #include <htio1/FastqSeq.h>
+ #include <htio1/QualityUtil.h>
+ #include <iostream>
+
+ int main(int argc, char** argv)
+ {
+ // create file handles
+ htio::FastqIO fh_in(argv[1], htio::HTIO_READ);
+
+ // read sequences
+ htio::FastqSeq seq;
+ while (fh_in.next_seq(seq))
+ {
+ std::cout << seq.id << std::endl;
+
+ // decode quality
+ std::vector<int16_t> quality_dec;
+ htio::decode_quality(seq.quality, quality_dec);
+
+ // show quality
+ for (size_t i=0; i<quality_dec.size(); i++)
+ {
+ if (quality_dec[i]<20)
+ std::cout << i+1 << ": " << quality_dec[i] << std::endl;
+ }
+ }
+ }
+
+Generate k-mers:
+
+ #include <htio1/FastqIO.h>
+ #include <htio1/FastqSeq.h>
+ #include <htio1/Kmer.h>
+ #include <iostream>
+
+ int main(int argc, char** argv)
+ {
+ // create file handles
+ htio::FastqIO fh_in(argv[1], htio::HTIO_READ);
+
+ // read sequences
+ htio::FastqSeq seq;
+ while (fh_in.next_seq(seq))
+ {
+ // convert atgcn to 01234
+ htio::EncodedSeq enc_seq;
+ htio::encode_nt(seq.seq, enc_seq);
+
+ // generate kmers, using a word size of six
+ htio::KmerList kmers;
+ htio::gen_kmer_nt(enc_seq, kmers, 6);
+
+ // summarize occurred position
+ htio::KmerPosMap kmer_pos;
+ htio::summ_kmer_pos(kmers, kmer_pos);
+
+ // show kmer and position
+ for (htio::KmerPosMap::iterator it = kmer_pos.begin(); it != kmer_pos.end(); it++)
+ std::cout << "kmer " << htio::decode_kmer_nt(it->first, 6) << " at " << it->second+1 << std::endl;
+ }
+ }
diff --git a/README-lane-tile.md b/README-lane-tile.md
new file mode 100644
index 0000000..b065fca
--- /dev/null
+++ b/README-lane-tile.md
@@ -0,0 +1,34 @@
+ht2-lane-tile - remove reads from specific lane/tile
+====================================================
+
+Introduction
+------------
+
+Tiles are rectangular areas in an Illumina sequencing chip. Sometimes, specific
+tiles may produce very few amount of acceptable reads, and some people think it
+is better to reject all reads from those tiles. Thus we provide this program to
+reject reads from specific tiles.
+
+Input and Output
+----------------
+
+This program do not distinguish single-end and paired-end inputs. Paired-end
+inputs can be processed by apply the program on each file.
+
+Usage
+-----
+
+Reject sequences from tile 2 and 3:
+
+ $ ht2-lane-tile -T 2 3 -i input.fastq -o output
+
+If your input file contains reads from multiple lanes, and you only wish to
+reject sequences from a specific lane-tile, you can specify lane number. For
+example, you want to reject tile 2 and 3 in lane 5:
+
+ $ ht2-lane-tile -L 5 -T 2 3 -i input.fastq -o output
+
+If you also want to get those rejected reads, specify the output prefix with
+`-u` option:
+
+ $ ht2-lane-tile -L 5 -T 2 3 -i input.fastq -o output -u rejected
diff --git a/README-overlap.md b/README-overlap.md
new file mode 100644
index 0000000..e9e3220
--- /dev/null
+++ b/README-overlap.md
@@ -0,0 +1,38 @@
+ht2-overlap - assemble overlapping read pairs
+=============================================
+
+Introduction
+------------
+
+Merge 3'-overlapping paired-end reads into single sequences.
+
+Input and output
+----------------
+
+Input should be paired-end reads. If read ends are stored in file pairs, all
+files of read 1 should be given firstly, then follwing all files of read 2.
+
+The assembled reads are written into one file. The non-assembled reads are
+written into file specified by "-u" option.
+
+Usage
+-----
+
+Default run:
+
+ $ ht2-overlap -i IN_1.fastq IN_2.fastq -o overlap
+
+If you also need those non-assembled reads, provide a file prefix using "-u"
+option:
+
+ $ ht2-overlap -i IN_1.fastq IN_2.fastq -o overlap -u non_overlap
+
+Files `non_overlap_1.fastq` and `non_overlap_2.fastq` will be generated.
+
+Assume your input reads are separated into multiple volumes. You can specify
+those input files via file globbing:
+
+ $ ls
+ IN_vol1_1.fastq IN_vol2_1.fastq IN_vol3_1.fastq
+ IN_vol1_2.fastq IN_vol2_2.fastq IN_vol3_2.fastq
+ $ht2-overlap -i IN_*_1.fastq IN_*_2.fastq -o overlap -u non_overlap
diff --git a/README-primer-trim.md b/README-primer-trim.md
new file mode 100644
index 0000000..2b230d6
--- /dev/null
+++ b/README-primer-trim.md
@@ -0,0 +1,80 @@
+ht2-primer-trim - find and remove primers from reads
+===================================================
+
+Introduction
+------------
+
+`ht2-primer-trim` removes primer sequences from reads. This task is common for
+sequencing on PCR-amplified products, such as 16S, ITS, and other phylogenetic
+marker sequences.
+
+Input and Output
+----------------
+
+The program accepts single- and paired-end input reads. The primer sequences
+should be given in one FASTA file. The ID of 5' primers should begin with
+"left", and 3' ones begin with "right". Output targets should be given by
+description. Multiplexed primers are accepted.
+
+Only the reads with primers are trimmed and written to output. User
+can specify a file prefix for those reads failed to found primers.
+
+For example:
+
+ >left1 16S
+ XXXXXXXXXXXXXXX
+ >left2 16S
+ XXXXXXXXXXXXXXX
+ >left3 ITS
+ XXXXXXXXXXXXXXX
+ >left4 ITS
+ XXXXXXXXXXXXXXX
+ >right1 16S
+ XXXXXXXXXXXXXXX
+ >right2 ITS
+ XXXXXXXXXXXXXXX
+
+ - if a sequence matches with left1 and right1, or left2 and right1, it will be
+ written to `OUT_DIR/16S.fastq`;
+
+ - if a sequences matches with left3 and right2, or left4 and right2, it will
+ be written to `OUT/ITS.fastq`;
+
+ - if a sequence matches with left1 and right2, or only match with one primer,
+ or don't match with any primers, it will be discarded, or written to the
+ file for failed sequences (if specified by user).
+
+Primer Matching Strategy
+------------------------
+
+When processing single-end reads, primers are attempted to be aligned in
+pattern below:
+
+ >>>> left primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ <<<< right primer <<<<
+
+If reverse-complement check is specified, the primers are
+also to be aligned in the pattern below:
+
+ >>>> right primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ <<<< left primer <<<<
+
+When processing paired-end reads, primers are attempted to be aligned in
+pattern below:
+
+ >>>> left primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read 1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+ >>>> right primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+If the reverse-complement check is specified, the primers are
+also to be aligned in the pattern below:
+
+ >>>> right primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read 1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+ >>>> left primer >>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>> read 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
diff --git a/README-rename.md b/README-rename.md
new file mode 100644
index 0000000..22f6d6b
--- /dev/null
+++ b/README-rename.md
@@ -0,0 +1,22 @@
+ht2-rename - generate simple sequence IDs by batch
+==================================================
+
+Introduction
+------------
+
+The original sequence ID usually contains detailed information and is very long.
+ht2-rename generates short ID by auto-incremented numbers and user-defined
+prefix|suffix.
+
+Input and Output
+----------------
+
+The program don't distinguish single-end and paired-end inputs. If the input
+sequences are paired-end in separate fils, just run the program on each file.
+
+Usage
+-----
+
+Generates IDs like PRE_1_SUFF, PRE_2_SUFF, PRE_3_SUFF...:
+
+ $ ht2-rename -i in_1.fastq -o renamed_1.fastq --prefix PRE_ --suffix _SUFF
diff --git a/README-sample.md b/README-sample.md
new file mode 100644
index 0000000..764c47a
--- /dev/null
+++ b/README-sample.md
@@ -0,0 +1,30 @@
+ht2-sample - randomly pick some reads
+====================================
+
+Introduction
+------------
+
+Sometimes you may want to randomly pick a fraction of sequences. ht2-sample
+picks a given fraction of sequences randomly.
+
+Note: the fraction is not exact. For example, if you have 1000 sequences and
+specified to pick 1/10 of them, you will **NOT** get exactly 100 sequences.
+This is a compromise to get better run-time performance.
+
+Input and output
+----------------
+
+This program accepts both single-end and paired-end reads. When paired-end reads
+is processed, the number of input files should be even, and the files of read 1
+should be given on front, then follwing the files of read 2.
+
+Usage
+-----
+
+Pick 1/100 of sequences, output will be written to sample.fastq:
+
+ $ ht2-sample -S -i in.fastq -o sample -r 100
+
+For paired-end, output will be written to sample_1.fastq and sample_2.fastq:
+
+ $ ht2-sample -P -i in_1.fastq in_2.fastq -o sample -r 100
diff --git a/README-stat.md b/README-stat.md
new file mode 100644
index 0000000..b6a63cd
--- /dev/null
+++ b/README-stat.md
@@ -0,0 +1,35 @@
+ht2-stat - summarize sequencing reads quality
+=============================================
+
+Introduction
+------------
+
+`ht2-stat` produces sequence assessment in following aspects:
+
+ - quality by cycle
+ - quality by lane/tile
+ - base composition by cycle
+ - quality histogram
+ - length histogram
+ - quality QQ plot for paired-end reads
+
+Input and output
+----------------
+
+The program accepts both single-end and paired-end reads. When paired-end reads
+is processed, the number of input files should be even, and the files of read
+1 should be given on front, then follwing the files of read 2.
+
+Results are written to a directory in plain-text tab-delimited format. If input
+is paired-end, the results for each end are placed in separated files.
+
+Usage
+-----
+
+Output files are placed in "qual_stat" folder:
+
+ $ ht2-stat -S -i in.fastq -o qual_stat
+
+For paired-end reads:
+
+ $ ht2-stat -P -i in_1.fastq in_2.fastq -o qual_stat
diff --git a/README-trim.md b/README-trim.md
new file mode 100644
index 0000000..c11abc6
--- /dev/null
+++ b/README-trim.md
@@ -0,0 +1,29 @@
+ht2-trim - remove bad residues from sequence start/end
+=====================================================
+
+Introduction
+------------
+
+The quality of sequencing reads from Illumina platform usually drops along
+length. ht2-trim can remove low-quality part from the start and the end of reads.
+
+The trim stops at the first *N* continuous bases in which qualities are all higher
+than *Q*. (N=5 and Q=20 by default).
+
+Input and output
+----------------
+
+The program don't distinguish single-end and paired-end inputs. If you need to
+process paired-end reads stored in separate file pairs, just run the program on
+each file.
+
+Usage
+-----
+
+Trim from both side:
+
+ $ ht2-trim -i in.fastq -o out.fastq
+
+Only trim from end, keep start:
+
+ $ ht2-trim --trim-side head -i in.fastq -o out.fastq
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6bb8be9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,151 @@
+HTQC - a high-throughput sequencing quality control toolkit
+===========================================================
+
+Introduction
+------------
+
+HTQC is a read quality control toolkit for high-throughput sequencing. It
+contain a program for quality statistics, and several programs for quality
+filtration.
+
+Currently, only Illumina sequencing platform is supported.
+
+System requirements
+-------------------
+
+- **Zlib** is required for build and run the programs.
+- **Perl** and **Chart::Clicker** are required to run "ht2-stat-draw.pl", which
+ renders the output tables of "ht2-stat" to charts.
+
+If you build HTQC from source:
+
+- The C++ compiler must have well-support on C++11. This means at least you need
+ GCC 4.8, clang 3.3 or MSVC 2010. Preferably, you should use GCC 4.9, clang 3.5
+ or MSVC 2013.
+
+- CMake is used for cross-platform build configuration.
+
+If your system don't have those softwares installed, please refer to your OS's
+package management system. For example: *yum* for Fedora; *apt-get*, *aptitude*
+and *synaptics* for Debian; *pacman* for Arch. Or you can visit their official
+website:
+
+-
+-
+- http://www.cmake.org
+
+Install
+-------
+
+See "INSTALL" document.
+
+List of Programs
+----------------
+
+- ht2-demul
+
+ separate reads into individual files by barcode sequence.
+
+- ht2-filter
+
+ filter reads by quality / length / tile ID.
+
+- ht2-overlap
+
+ concatenate paired-end reads into single sequences.
+
+- ht2-primer-trim
+
+ remove primer sequences from reads.
+
+- ht2-rename
+
+ give sequences short name using auto-increased number and user-specified
+ prefix & suffix.
+
+- ht2-sample
+
+ randomly pick some sequences.
+
+- ht2-stat
+
+ generate reads quality statistics report.
+
+- ht2-stat-draw.pl
+
+ draw charts from ht2-stat output.
+
+- ht2-trim
+
+ trim reads from start and/or end by quality.
+
+For detailed descriptions, see individual README-XXX files for each program.
+Run a program with "-h" or "--help" will show command-line options.
+
+Typical usage
+-------------
+
+First of all, to know whether the sequencing reads are good:
+
+ $ ht2-stat -P -i reads_R1_* reads_R2_* -o report_dir
+ $ ht2-stat-draw.pl --dir report_dir
+
+Suppose it shows tile 5 and 14 is bad. Remove reads from these tiles:
+
+ $ ht2-lane-tile -i reads_R1_* --tile 5 14 -o tile_tidy_1
+ $ ht2-lane-tile -i reads_R2_* --tile 5 14 -o tile_tidy_2
+
+Trim low-quality tails:
+
+ $ ht2-trim -i tile_tidy_1.fastq -o trim_1.fastq
+ $ ht2-trim -i tile_tidy_2.fastq -o trim_2.fastq
+
+Remove reads that are too short:
+
+ $ ht2-filter -i trim_1.fastq trim_2.fastq -o filt
+
+Maybe you want to concatenate paired-ends to longer sequences:
+
+ $ ht2-overlap -i filt_1.fastq filt_2.fastq -o overlap -u non_overlap
+
+Single-end or pair-end
+----------------------
+
+Some programs handle single-end and paired-end reads differently. For those
+programs, outputs files are specified by a prefix, and multiple files will
+generated. For "ht2-filter", when one end of a paired-end is rejected but the
+other end is accepted, it is stored to "PREFIX_s.fastq".
+
+Programs like "ht2-trim" don't distinguish between paired-end or single-end
+mode. It only accepts one input file and one output file. You should run them
+twice for paired-end reads, one time for the file of each end.
+
+Reference
+---------
+
+We would be really appreciated if you cite our article:
+
+Yang X, Liu D, Liu F, Wu J, Zou J, Xiao X, Zhao F, Zhu B.
+HTQC: a fast quality control toolkit for Illumina sequencing data.
+BMC Bioinformatics. 2013 Jan 31;14:33
+
+Acknowledgements
+----------------
+
+JUCE core library is used for part of the base system. It is a light-weighted
+library whose source can be contained and compiled with our project. Thanks for
+the developers of JUCE! It's great!!!
+
+Contact
+-------
+
+If you have any questions or find any bugs, please email us:
+
+developer:
+
+- Xi Yang: jiandingzhe at 163.com, yangx at im.ac.cn
+- Di Liu: liud at im.ac.cn
+
+corresponding author:
+
+- Baoli Zhu: zhubaoli at im.ac.cn
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..a3bb0fc
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,101 @@
+configure_file(ht_config.h.in ht_config.h @ONLY)
+configure_file(htio2/config.h.in htio2/config.h @ONLY)
+
+file(GLOB HTIO_SOURCE_FILES htio2/*.cpp)
+file(GLOB HTQC_SOURCE_FILES htqc/*.cpp)
+file(GLOB JUCE_SOURCE_FILES htio2/JUCE-3.0.8/modules/*/*.cpp)
+
+add_library(htio2 STATIC ${HTIO_SOURCE_FILES} ${JUCE_SOURCE_FILES})
+
+add_library(ht_common STATIC ${HTQC_SOURCE_FILES})
+
+add_executable(ht2-convert ht2-convert.cpp)
+target_link_libraries(ht2-convert
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-demul ht2-demul.cpp)
+target_link_libraries(ht2-demul
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-stat ht2-stat.cpp
+ htqc/BaseQualCounter.cpp
+ htqc/FastqStat.cpp
+)
+target_link_libraries(ht2-stat
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-trim ht2-trim.cpp)
+target_link_libraries(ht2-trim
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-filter ht2-filter.cpp)
+target_link_libraries(ht2-filter
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-rename ht2-rename.cpp)
+target_link_libraries(ht2-rename
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-sample ht2-sample.cpp)
+target_link_libraries(ht2-sample
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-overlap ht2-overlap.cpp)
+target_link_libraries(ht2-overlap
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-primer-trim ht2-primer-trim.cpp)
+target_link_libraries(ht2-primer-trim
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(ht2-lane-tile ht2-lane-tile.cpp)
+target_link_libraries(ht2-lane-tile
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+install(TARGETS ht2-demul ht2-primer-trim ht2-convert ht2-stat ht2-trim ht2-filter ht2-sample ht2-overlap ht2-rename htio2
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+install(PROGRAMS ht2-stat-draw.pl DESTINATION bin)
+install(FILES ${CMAKE_BINARY_DIR}/src/htio2/config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/htio2)
+install(DIRECTORY htio2/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/htio2 FILES_MATCHING PATTERN "*.h")
diff --git a/src/ht2-convert.cpp b/src/ht2-convert.cpp
new file mode 100644
index 0000000..3110e6a
--- /dev/null
+++ b/src/ht2-convert.cpp
@@ -0,0 +1,238 @@
+#include <htio2/PairedEndIO.h>
+#include <htio2/QualityUtil.h>
+#include "htio2/Cast.h"
+#include "htio2/SeqIO.h"
+
+#define USE_prefix_out
+#define USE_se_pe
+#define USE_encode
+#define USE_header_format
+#include <htqc/Options.h>
+#include <htqc/App.h>
+#include <htqc/MultiSeqFile.h>
+
+using namespace std;
+using namespace htqc;
+
+bool OPT_out_pe_itlv;
+htio2::Option OPT_out_pe_itlv_ENTRY("out-pe-itlv", '\0', OPTION_GROUP_FORMAT,
+ &OPT_out_pe_itlv, htio2::Option::FLAG_NONE,
+ "Output paired-end reads will be stored in interleaved format.");
+
+string OPT_out_pe_strand("FR");
+htio2::Option OPT_out_pe_strand_ENTRY("out-pe-strand", '\0', OPTION_GROUP_FORMAT,
+ &OPT_out_pe_strand, htio2::Option::FLAG_NONE,
+ "The strand of paired-end reads for output. \"F\" for forward, \"R\" for reverse. 1st character for read 1, 2nd character for read 2.",
+ "FF|FR|RF|RR");
+
+htio2::QualityEncode OPT_out_encode;
+htio2::Option OPT_out_encode_ENTRY("out-encode", '\0', OPTION_GROUP_FORMAT,
+ &OPT_out_encode, htio2::Option::FLAG_NONE,
+ "Output quality score encode.", "STRING");
+
+htio2::Strand OPT_out_pe_strand1()
+{
+ return _cast_strand_chr(OPT_out_pe_strand[0]);
+}
+
+htio2::Strand OPT_out_pe_strand2()
+{
+ return _cast_strand_chr(OPT_out_pe_strand[1]);
+}
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser option_parser;
+ option_parser.add_option(OPT_files_in_ENTRY);
+ option_parser.add_option(OPT_prefix_out_ENTRY);
+ option_parser.add_option(OPT_se_ENTRY);
+ option_parser.add_option(OPT_pe_ENTRY);
+
+ option_parser.add_option(OPT_encode_ENTRY);
+ option_parser.add_option(OPT_pe_itlv_ENTRY);
+ option_parser.add_option(OPT_pe_strand_ENTRY);
+
+ option_parser.add_option(OPT_out_encode_ENTRY);
+ option_parser.add_option(OPT_out_pe_itlv_ENTRY);
+ option_parser.add_option(OPT_out_pe_strand_ENTRY);
+
+ option_parser.add_option(OPT_quiet_ENTRY);
+ option_parser.add_option(OPT_help_ENTRY);
+ option_parser.add_option(OPT_version_ENTRY);
+
+ option_parser.parse_options(argc, argv);
+
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - convert paired-end reads from interleaved format to file pairs, or reverse"<< endl
+ << endl
+ << option_parser.format_document();
+ exit(EXIT_SUCCESS);
+ }
+ if (OPT_version) htqc::show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_prefix_out();
+ ensure_se_pe();
+ ensure_encode();
+ ensure_header_format();
+
+ if (OPT_pe)
+ {
+ if (OPT_out_pe_strand == "unknown")
+ OPT_out_pe_strand = _OPT_pe_strand;
+
+ if (OPT_out_pe_strand.length() != 2
+ || !check_strand_chr(OPT_out_pe_strand[0])
+ || !check_strand_chr(OPT_out_pe_strand[1]))
+ {
+ cerr << "ERROR: invalid paired-end strand: " << OPT_out_pe_strand << endl
+ << "Valid values: FF/FR/RF/RR (lower case allowed)." << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (OPT_out_encode == htio2::ENCODE_UNKNOWN)
+ OPT_out_encode = OPT_encode;
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ show_encode();
+ show_prefix_out();
+ cout << "# output encode: " << htio2::to_string(OPT_out_encode) << endl;
+ if (OPT_pe)
+ {
+ cout << "# output strand: " << OPT_out_pe_strand << endl;
+ if (OPT_out_pe_itlv)
+ cout << "# output is interleaved" << endl;
+ }
+}
+
+void do_se()
+{
+ // output file name
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+
+ // io handles
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+ htio2::SeqIO::Ptr fh_out(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+
+ // traverse sequences
+ htio2::FastqSeq seq;
+ vector<int16_t> qual;
+
+ size_t n_seq = 0;
+
+ while (fh_in.next_seq(seq))
+ {
+ n_seq++;
+ if (OPT_encode != OPT_out_encode)
+ {
+ htio2::decode_quality(seq.quality, qual, OPT_encode);
+ htio2::encode_quality(qual, seq.quality, OPT_out_encode);
+ }
+ fh_out->write_seq(seq);
+ if (!OPT_quiet && n_seq % LOG_BLOCK == 0)
+ cout << " " << n_seq << " processed" << endl;
+ }
+
+ if (!OPT_quiet)
+ cout << " " << n_seq << " processed" << endl;
+}
+
+void do_pe()
+{
+ htqc::MultiSeqFilePE* fh_in;
+ htio2::PairedEndIO* fh_out;
+
+ htio2::Strand strand_in1 = OPT_pe_strand1();
+ htio2::Strand strand_in2 = OPT_pe_strand2();
+
+ if (OPT_pe_itlv)
+ {
+ fh_in = new htqc::MultiSeqFilePE(OPT_files_in,
+ strand_in1, strand_in2,
+ OPT_compress);
+ }
+ else
+ {
+ vector<string> files1;
+ vector<string> files2;
+ separate_paired_files(OPT_files_in, files1, files2);
+ fh_in = new htqc::MultiSeqFilePE(files1, files2,
+ strand_in1, strand_in2,
+ OPT_compress);
+ }
+
+ if (OPT_out_pe_itlv)
+ {
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ fh_out = new htio2::PairedEndIO(file_out,
+ htio2::WRITE,
+ OPT_out_pe_strand1(), OPT_out_pe_strand2(),
+ OPT_compress);
+ }
+ else
+ {
+ string file_out1;
+ string file_out2;
+ add_fastq_suffix_pe(OPT_prefix_out, OPT_compress, file_out1, file_out2);
+ check_output_overwrite(OPT_files_in, file_out1);
+ check_output_overwrite(OPT_files_in, file_out2);
+ fh_out = new htio2::PairedEndIO(file_out1, file_out2,
+ htio2::WRITE,
+ OPT_out_pe_strand1(), OPT_out_pe_strand2(),
+ OPT_compress);
+ }
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+ vector<int16_t> qual1;
+ vector<int16_t> qual2;
+
+ size_t n_seq = 0;
+
+ while (fh_in->next_pair(seq1, seq2, strand_in1, strand_in2))
+ {
+ n_seq++;
+ if (OPT_encode != OPT_out_encode)
+ {
+ htio2::decode_quality(seq1.quality, qual1, OPT_encode);
+ htio2::decode_quality(seq2.quality, qual2, OPT_encode);
+ htio2::encode_quality(qual1, seq1.quality, OPT_out_encode);
+ htio2::encode_quality(qual2, seq2.quality, OPT_out_encode);
+ }
+
+ fh_out->write_pair(seq1, seq2, strand_in1, strand_in2);
+ if (!OPT_quiet && n_seq % LOG_BLOCK == 0)
+ cout << " " << n_seq << " pairs processed" << endl;
+ }
+
+ if (!OPT_quiet)
+ cout << " " << n_seq << " pairs processed" << endl;
+
+ delete fh_in;
+ delete fh_out;
+}
+
+void execute()
+{
+ if (OPT_se)
+ do_se();
+ else if (OPT_pe)
+ do_pe();
+ else
+ throw runtime_error("neither single-end nor paired-end");
+}
+
diff --git a/src/ht2-demul.cpp b/src/ht2-demul.cpp
new file mode 100644
index 0000000..83a95dc
--- /dev/null
+++ b/src/ht2-demul.cpp
@@ -0,0 +1,438 @@
+#include "htio2/Cast.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/PairedEndIO.h"
+#include "htio2/PlainFileHandle.h"
+#include "htio2/HeaderUtil.h"
+
+#define USE_header_format
+#define USE_se_pe
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+#include "htio2/JUCE-3.0.8/JuceHeader.h"
+
+#include <set>
+
+// We don't care strand in this program, so simply let them identical.
+#define PE_STRAND_FILE htio2::STRAND_FWD, htio2::STRAND_FWD
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_FWD
+
+using namespace std;
+using namespace htqc;
+using namespace htio2::juce;
+
+string OPT_dir_out;
+htio2::Option OPT_dir_out_ENTRY("out", 'o', OPTION_GROUP_IO,
+ &OPT_dir_out, htio2::Option::FLAG_NONE,
+ "Output directory.", "DIR");
+string OPT_file_barcode;
+htio2::Option OPT_file_barcode_ENTRY("barcode", '\0', OPTION_GROUP_IO,
+ &OPT_file_barcode, htio2::Option::FLAG_NONE,
+ "Tab-delimited file containing three columns which are project, sample and barcode. Output will be written to output_dir/project/sample_[12].fastq",
+ "FILE");
+
+int OPT_mismatch(0);
+htio2::Option OPT_mismatch_ENTRY("mismatch", '\0', "Algorithm Parameters",
+ &OPT_mismatch, htio2::Option::FLAG_NONE,
+ "Allowed number of barcode mismatch.", "INT");
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser option_parser;
+ option_parser.add_option(OPT_files_in_ENTRY);
+ option_parser.add_option(OPT_dir_out_ENTRY);
+ option_parser.add_option(OPT_file_barcode_ENTRY);
+
+ option_parser.add_option(OPT_mismatch_ENTRY);
+
+ option_parser.add_option(OPT_se_ENTRY);
+ option_parser.add_option(OPT_pe_ENTRY);
+ option_parser.add_option(OPT_pe_itlv_ENTRY);
+ option_parser.add_option(OPT_pe_strand_ENTRY);
+ option_parser.add_option(OPT_header_format_ENTRY);
+ option_parser.add_option(OPT_header_sra_ENTRY);
+
+ option_parser.add_option(OPT_quiet_ENTRY);
+ option_parser.add_option(OPT_help_ENTRY);
+ option_parser.add_option(OPT_version_ENTRY);
+
+ option_parser.parse_options(argc, argv);
+
+ // show help
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - demultiplex reads by barcode"
+ << endl << endl
+ << option_parser.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_se_pe();
+
+ if (!OPT_dir_out.length())
+ {
+ cerr << "ERROR: output directory not specified" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ ensure_header_format();
+
+ if (OPT_header_format != htio2::HEADER_1_8)
+ {
+ cerr << "ERROR: only CASAVA 1.8 headers can be used for demultiplex" << endl
+ << "your header format is: " << htio2::to_string(OPT_header_format) << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ cout << "# output dir: " << OPT_dir_out << endl;
+ cout << "# barcode file: " << OPT_file_barcode << endl;
+ cout << "# barcode mismatch: " << OPT_mismatch << endl;
+ show_header_format();
+}
+
+void read_barcode(map<string, pair<string, string> > & barcodes)
+{
+ if (!OPT_quiet)
+ cout << "read barcode file" << endl;
+ barcodes.clear();
+
+ htio2::PlainFileHandle IN(OPT_file_barcode.c_str(), htio2::READ);
+ string buffer;
+
+ while (IN.read_line(buffer))
+ {
+ size_t tab1 = buffer.find_first_of('\t');
+ size_t tab2 = buffer.find_first_of('\t', tab1 + 1);
+ string proj(buffer.substr(0, tab1));
+ string sample(buffer.substr(tab1 + 1, tab2 - tab1 - 1));
+ string barcode(buffer.substr(tab2 + 1));
+
+ if (!barcodes.insert(make_pair(barcode, make_pair(proj, sample))).second)
+ {
+ cerr << "ERROR: duplicate barcode: " << barcode << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void gen_output_dir(const map<string, pair<string, string> > & barcodes)
+{
+ if (!OPT_quiet) cout << "create output directories" << endl;
+
+ File p_out(OPT_dir_out.c_str());
+
+ if (!p_out.isDirectory())
+ {
+ Result re = p_out.createDirectory();
+ if (re.failed())
+ {
+ fprintf(stderr, "ERROR: failed to create output directory \"%s\": %s\n",
+ OPT_dir_out.c_str(), re.getErrorMessage().toRawUTF8());
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ set<string> projs;
+ for (map<string, pair<string, string> >::const_iterator it = barcodes.begin(); it != barcodes.end(); it++)
+ {
+ projs.insert(it->second.first);
+ }
+
+ for (set<string>::const_iterator it = projs.begin(); it != projs.end(); it++)
+ {
+ File p_out_proj = p_out.getChildFile(it->c_str());
+
+ // remove existing directory
+ if (p_out_proj.isDirectory())
+ {
+ if (!OPT_quiet)
+ printf(" remove existing dir \"%s\"\n", p_out_proj.getFullPathName().toRawUTF8());
+
+ if (!p_out_proj.deleteRecursively())
+ {
+ fprintf(stderr, "ERROR: failed to remove dir \"%s\"\n", p_out_proj.getFullPathName().toRawUTF8());
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // create new directory
+ if (!OPT_quiet)
+ cout << " create output dir: " << p_out_proj.getFullPathName().toStdString() << endl;
+
+ Result re = p_out_proj.createDirectory();
+ if (re.failed())
+ {
+ fprintf(stderr, "ERROR: failed to create output directory \"%s\": %s\n",
+ p_out_proj.getFullPathName().toRawUTF8(), re.getErrorMessage().toRawUTF8());
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+bool check_barcode(const map<string, pair<string, string> > & barcodes,
+ const string& barcode,
+ string& proj,
+ string& sample)
+{
+ map<string, pair<string, string> >::const_iterator it = barcodes.find(barcode);
+
+ if (it != barcodes.end())
+ {
+ proj = it->second.first;
+ sample = it->second.second;
+ return true;
+ }
+ else if (OPT_mismatch)
+ {
+ for (it = barcodes.begin(); it != barcodes.end(); it++)
+ {
+ const string& ref_barcode = it->first;
+ if (ref_barcode.length() != barcode.length()) continue;
+ size_t diff = 0;
+ for (size_t i = 0; i < ref_barcode.length(); i++)
+ {
+ if (ref_barcode[i] != barcode[i]) diff++;
+ }
+
+ if (diff <= OPT_mismatch)
+ {
+ proj = it->second.first;
+ sample = it->second.second;
+ return true;
+ }
+ }
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+int64_t n_accept = 0;
+int64_t n_seq = 0;
+
+string gen_out_file_one(const string& proj, const string& sample)
+{
+ File prefix = File(OPT_dir_out).getChildFile(String(proj)).getChildFile(String(sample));
+ string file_out;
+ add_fastq_suffix_se(prefix.getFullPathName().toStdString(), OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ return file_out;
+}
+
+void gen_out_file_pair(const string& proj, const string& sample, string& f1, string& f2)
+{
+ File prefix = File(OPT_dir_out).getChildFile(String(proj)).getChildFile(String(sample));
+ add_fastq_suffix_pe(prefix.getFullPathName().toStdString(), OPT_compress, f1, f2);
+ check_output_overwrite(OPT_files_in, f1);
+ check_output_overwrite(OPT_files_in, f2);
+}
+
+string gen_fail_file_one()
+{
+ File prefix = File(OPT_dir_out).getChildFile("demul_failed");
+ string file_out;
+ add_fastq_suffix_se(prefix.getFullPathName().toStdString(), OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ return file_out;
+}
+
+void gen_fail_file_pair(string& f1, string& f2)
+{
+ File prefix = File(OPT_dir_out).getChildFile("demul_failed");
+ add_fastq_suffix_pe(prefix.getFullPathName().toStdString(), OPT_compress, f1, f2);
+ check_output_overwrite(OPT_files_in, f1);
+ check_output_overwrite(OPT_files_in, f2);
+}
+
+void do_se(const map<string, pair<string, string> > & barcodes)
+{
+ htio2::FastqSeq curr_seq;
+ htio2::HeaderParser parser(OPT_header_format, OPT_header_sra);
+ string proj;
+ string sample;
+
+ int64_t n_accept = 0;
+ int64_t n_seq = 0;
+
+ string file_fail = gen_fail_file_one();
+
+ htio2::FastqIO FAIL(file_fail, htio2::WRITE, OPT_compress);
+
+ for (size_t file_i = 0; file_i < OPT_files_in.size(); file_i++)
+ {
+ htio2::FastqIO IN(OPT_files_in[file_i], htio2::READ, OPT_compress);
+
+ while (IN.next_seq(curr_seq))
+ {
+ parser.parse(curr_seq.id, curr_seq.desc);
+
+ if (check_barcode(barcodes, parser.barcode, proj, sample))
+ {
+ string file_out = gen_out_file_one(proj, sample);
+ htio2::FastqIO OUT(file_out, htio2::APPEND, OPT_compress);
+ OUT.write_seq(curr_seq);
+ n_accept++;
+ }
+ else
+ {
+ FAIL.write_seq(curr_seq);
+ }
+
+ n_seq++;
+ if (!OPT_quiet && n_accept % LOG_BLOCK == 0)
+ cout << " " << n_seq << " sequences, " << n_accept << " has barcode" << endl;
+ }
+ }
+
+ if (!OPT_quiet)
+ cout << " " << n_seq << " sequences, " << n_accept << " has barcode" << endl;
+}
+
+void process_one_pe(const htio2::FastqSeq& seq1,
+ const htio2::FastqSeq& seq2,
+ htio2::PairedEndIO& fh_fail,
+ const map<string, pair<string, string> > & barcodes,
+ htio2::HeaderParser& parser1,
+ htio2::HeaderParser& parser2)
+{
+ n_seq++;
+
+ string proj;
+ string sample;
+
+ parser1.parse(seq1.id, seq1.desc);
+ parser2.parse(seq2.id, seq2.desc);
+
+ if (parser1.barcode != parser2.barcode)
+ {
+ cerr << "ERROR: paired-end has conflict barcodes: " << endl
+ << parser1.barcode << endl
+ << parser2.barcode << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (check_barcode(barcodes, parser1.barcode, proj, sample))
+ {
+ n_accept++;
+
+ if (OPT_pe_itlv)
+ {
+ string file_out = gen_out_file_one(proj, sample);
+ htio2::PairedEndIO fh_out(file_out,
+ htio2::APPEND,
+ PE_STRAND_FILE,
+ OPT_compress);
+ fh_out.write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+ else
+ {
+ string f1;
+ string f2;
+ gen_out_file_pair(proj, sample, f1, f2);
+ htio2::PairedEndIO fh_out(f1,
+ f2,
+ htio2::APPEND,
+ PE_STRAND_FILE,
+ OPT_compress);
+ fh_out.write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+ }
+ else
+ {
+ fh_fail.write_pair(seq1, seq2);
+ }
+
+ if (!OPT_quiet && n_accept % LOG_BLOCK == 0)
+ cout << " " << n_seq << " paired-ends, " << n_accept << " has barcode" << endl;
+}
+
+void do_pe(const map<string, pair<string, string> > & barcodes)
+{
+ htio2::FastqSeq curr1;
+ htio2::FastqSeq curr2;
+ htio2::HeaderParser parser1(OPT_header_format, OPT_header_sra);
+ htio2::HeaderParser parser2(OPT_header_format, OPT_header_sra);
+
+ if (!OPT_quiet)
+ cout << "traverse input files" << endl;
+
+ if (OPT_pe_itlv)
+ {
+ // create handle for failed output
+ string file_fail = gen_fail_file_one();
+
+ htio2::PairedEndIO fh_fail(file_fail,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ // traverse input files
+ htqc::MultiSeqFilePE fh_in(OPT_files_in, PE_STRAND_FILE, OPT_compress);
+
+ while (fh_in.next_pair(curr1, curr2, PE_STRAND_OBJ))
+ {
+ process_one_pe(curr1, curr2, fh_fail, barcodes, parser1, parser2);
+ }
+ }
+ else
+ {
+ string file_fail1;
+ string file_fail2;
+ gen_fail_file_pair(file_fail1, file_fail2);
+
+ htio2::PairedEndIO fh_fail(file_fail1,
+ file_fail2,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+
+ // traverse input file pairs
+ htqc::MultiSeqFilePE fh_in(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ while (fh_in.next_pair(curr1, curr2, PE_STRAND_OBJ))
+ {
+ process_one_pe(curr1, curr2, fh_fail, barcodes, parser1, parser2);
+ }
+ }
+
+ if (!OPT_quiet)
+ cout << "done: " << n_seq << " paired-ends, " << n_accept << " has barcode" << endl;
+}
+
+void execute()
+{
+ map<string, pair<string, string> > barcodes;
+
+ read_barcode(barcodes);
+ gen_output_dir(barcodes);
+
+ if (OPT_se)
+ do_se(barcodes);
+ else if (OPT_pe)
+ do_pe(barcodes);
+ else
+ throw runtime_error("neither single-end nor paired-end");
+}
diff --git a/src/ht2-filter.cpp b/src/ht2-filter.cpp
new file mode 100644
index 0000000..9e31db3
--- /dev/null
+++ b/src/ht2-filter.cpp
@@ -0,0 +1,340 @@
+#define USE_prefix_out
+#define USE_encode
+#define USE_mask
+#define USE_header_format
+#define USE_se_pe
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+#include "htio2/SeqIO.h"
+#include "htio2/PairedEndIO.h"
+#include "htio2/QualityUtil.h"
+
+// We don't care strand in this program, so simply let them identical.
+#define PE_STRAND_FILE htio2::STRAND_FWD, htio2::STRAND_FWD
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_FWD
+
+using namespace std;
+using namespace htqc;
+
+string OPT_prefix_reject;
+htio2::Option OPT_prefix_reject_ENTRY("reject", 'u', OPTION_GROUP_IO,
+ &OPT_prefix_reject, htio2::Option::FLAG_NONE,
+ "Output file prefix for rejected sequences.", "FILE_PREFIX");
+
+size_t OPT_cut_len(80);
+htio2::Option OPT_cut_len_ENTRY("length", 'L', "Filter Options",
+ &OPT_cut_len, htio2::Option::FLAG_NONE,
+ "Cutoff for the length of high-quality base pairs.", "INT");
+
+int16_t OPT_cut_qual(20);
+htio2::Option OPT_cut_qual_ENTRY("quality", 'Q', "Filter Options",
+ &OPT_cut_qual, htio2::Option::FLAG_NONE,
+ "Cutoff for base pair quality.", "INT");
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser opt_psr;
+
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+ opt_psr.add_option(OPT_prefix_reject_ENTRY);
+
+ opt_psr.add_option(OPT_se_ENTRY);
+ opt_psr.add_option(OPT_pe_ENTRY);
+ opt_psr.add_option(OPT_pe_itlv_ENTRY);
+
+ opt_psr.add_option(OPT_cut_len_ENTRY);
+ opt_psr.add_option(OPT_cut_qual_ENTRY);
+
+ opt_psr.add_option(OPT_encode_ENTRY);
+ opt_psr.add_option(OPT_mask_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ // show help
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - filter sequences by length and quality"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_prefix_out();
+ ensure_se_pe();
+ ensure_encode();
+
+ if (OPT_prefix_reject.length())
+ tidy_prefix_out(OPT_prefix_reject);
+
+ if (OPT_prefix_out == OPT_prefix_reject)
+ {
+ cerr << "conflict output prefix for accepted and rejected reads: \"" << OPT_prefix_reject << "\"" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ show_prefix_out();
+
+ if (OPT_prefix_reject.length())
+ cout << "# file prefix for rejected reads: " << OPT_prefix_reject << endl;
+
+ cout << "# length cutoff: " << OPT_cut_len << endl;
+ cout << "# quality cutoff: " << OPT_cut_qual << endl;
+ show_encode();
+}
+
+bool validate_seq(const htio2::FastqSeq& seq)
+{
+ vector<int16_t> qual;
+ htio2::decode_quality(seq.quality, qual, OPT_encode);
+
+ size_t high_qual_len = 0;
+ for (size_t i = 0; i < seq.length(); i++)
+ {
+ if (qual[i] >= OPT_cut_qual)
+ high_qual_len++;
+ }
+
+ return (high_qual_len >= OPT_cut_len);
+}
+
+void filter_se()
+{
+ // input
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ // output
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ htio2::SeqIO::Ptr fh_out(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+
+ // rejected
+ htio2::SeqIO::Ptr fh_fail;
+ if (OPT_prefix_reject.length())
+ {
+ string file_fail;
+ add_fastq_suffix_se(OPT_prefix_reject, OPT_compress, file_fail);
+ check_output_overwrite(OPT_files_in, file_fail);
+ fh_fail = htio2::SeqIO::New(file_fail, htio2::WRITE, OPT_compress);
+ }
+
+ // traverse input
+ htio2::FastqSeq curr_seq;
+ int64_t n_accept = 0;
+ int64_t n_seq = 0;
+
+ while (fh_in.next_seq(curr_seq))
+ {
+ n_seq++;
+
+ if (validate_seq(curr_seq))
+ {
+ fh_out->write_seq(curr_seq);
+ n_accept++;
+ }
+ else
+ {
+ if (OPT_prefix_reject.length())
+ fh_fail->write_seq(curr_seq);
+ }
+
+ if (!OPT_quiet && (n_seq % LOG_BLOCK == 0))
+ cout << "\t" << n_seq << " reads, " << n_accept << " accept" << endl;
+ }
+
+ if (!OPT_quiet)
+ cout << "\t" << n_seq << " reads, " << n_accept << " accept" << endl;
+}
+
+int64_t n_accept_pair = 0;
+int64_t n_accept_single = 0;
+int64_t n_pair = 0;
+
+void filter_one_pe(const htio2::FastqSeq& seq1,
+ const htio2::FastqSeq& seq2,
+ htio2::PairedEndIO* fh_out,
+ htio2::SeqIO* fh_single,
+ htio2::PairedEndIO* fh_fail_pair,
+ htio2::SeqIO* fh_fail_single)
+{
+ n_pair++;
+
+ bool accept_a = validate_seq(seq1);
+ bool accept_b = validate_seq(seq2);
+
+ if (accept_a)
+ {
+ if (accept_b)
+ {
+ fh_out->write_pair(seq1, seq2, PE_STRAND_OBJ);
+ n_accept_pair++;
+ }
+ else
+ {
+ fh_single->write_seq(seq1);
+ if (OPT_prefix_reject.length())
+ fh_fail_single->write_seq(seq2);
+ n_accept_single++;
+ }
+ }
+ else
+ {
+ if (accept_b)
+ {
+ if(OPT_prefix_reject.length())
+ fh_fail_single->write_seq(seq1);
+ fh_single->write_seq(seq2);
+ n_accept_single++;
+ }
+ else
+ {
+ if (OPT_prefix_reject.length())
+ fh_fail_pair->write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+ }
+
+ if (!OPT_quiet && (n_pair % LOG_BLOCK == 0))
+ cout << "\t" << n_pair << " pairs, " << n_accept_pair << " accept by pair, " << n_accept_single << " accept by single" << endl;
+}
+
+void filter_pe()
+{
+ // generate output file name for one-side-accepted reads
+ string file_out_s;
+ add_fastq_suffix_se(OPT_prefix_out + "_s", OPT_compress, file_out_s);
+ check_output_overwrite(OPT_files_in, file_out_s);
+
+ string file_fail_s;
+ if (OPT_prefix_reject.length())
+ {
+ add_fastq_suffix_se(OPT_prefix_reject + "_s", OPT_compress, file_fail_s);
+ check_output_overwrite(OPT_files_in, file_fail_s);
+ }
+
+ // tmp sequence
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ if (OPT_pe_itlv)
+ {
+ // input
+ htqc::MultiSeqFilePE fh_in(OPT_files_in,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ // output
+ string file_out_p;
+ add_fastq_suffix_se(OPT_prefix_out + "_p", OPT_compress, file_out_p);
+ check_output_overwrite(OPT_files_in, file_out_p);
+
+ htio2::PairedEndIO::Ptr fh_out_p(new htio2::PairedEndIO(file_out_p,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress)
+ );
+
+ htio2::SeqIO::Ptr fh_out_s(htio2::SeqIO::New(file_out_s,
+ htio2::WRITE,
+ OPT_compress)
+ );
+
+ // fail
+ htio2::PairedEndIO::Ptr fh_fail_p;
+ htio2::SeqIO::Ptr fh_fail_s;
+
+ if (OPT_prefix_reject.length())
+ {
+ string file_fail_p;
+ add_fastq_suffix_se(OPT_prefix_reject + "_p", OPT_compress, file_fail_p);
+ check_output_overwrite(OPT_files_in, file_fail_p);
+
+ fh_fail_p = new htio2::PairedEndIO(file_fail_p, htio2::WRITE, PE_STRAND_FILE, OPT_compress);
+ fh_fail_s = htio2::SeqIO::New(file_fail_s, htio2::WRITE, OPT_compress);
+ }
+
+ // traverse input files
+ while (fh_in.next_pair(seq1, seq2, PE_STRAND_OBJ))
+ filter_one_pe(seq1, seq2, fh_out_p.get(), fh_out_s.get(), fh_fail_p.get(), fh_fail_s.get());
+ }
+ else
+ {
+ // input
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+ htqc::MultiSeqFilePE fh_in(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+
+ // output
+ string file_out_a;
+ string file_out_b;
+ add_fastq_suffix_pe(OPT_prefix_out, OPT_compress, file_out_a, file_out_b);
+ check_output_overwrite(OPT_files_in, file_out_a);
+ check_output_overwrite(OPT_files_in, file_out_b);
+
+ htio2::PairedEndIO::Ptr fh_out_p(new htio2::PairedEndIO(file_out_a,
+ file_out_b,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress)
+ );
+
+ htio2::SeqIO::Ptr fh_out_s(htio2::SeqIO::New(file_out_s,
+ htio2::WRITE,
+ OPT_compress)
+ );
+
+ // fail
+ htio2::PairedEndIO::Ptr fh_fail_p;
+ htio2::SeqIO::Ptr fh_fail_s;
+ if (OPT_prefix_reject.length())
+ {
+ string file_fail_a, file_fail_b;
+ add_fastq_suffix_pe(OPT_prefix_reject, OPT_compress, file_fail_a, file_fail_b);
+ check_output_overwrite(OPT_files_in, file_fail_a);
+ check_output_overwrite(OPT_files_in, file_fail_b);
+
+ fh_fail_p = new htio2::PairedEndIO(file_fail_a, file_fail_b, htio2::WRITE, PE_STRAND_FILE, OPT_compress);
+ fh_fail_s = htio2::SeqIO::New(file_fail_s, htio2::WRITE, OPT_compress);
+ }
+
+ // traverse input files
+ while (fh_in.next_pair(seq1, seq2, PE_STRAND_OBJ))
+ filter_one_pe(seq1, seq2, fh_out_p.get(), fh_out_s.get(), fh_fail_p.get(), fh_fail_s.get());
+ }
+
+ if (!OPT_quiet)
+ cout << "\t" << n_pair << " input, " << n_accept_pair << " accept by pair, " << n_accept_single << " accept by single" << endl;
+}
+
+void execute()
+{
+ if (OPT_se)
+ filter_se();
+ else if (OPT_pe)
+ filter_pe();
+ else
+ throw runtime_error("neither single-end nor paired-end");
+}
diff --git a/src/ht2-lane-tile.cpp b/src/ht2-lane-tile.cpp
new file mode 100644
index 0000000..392c3d5
--- /dev/null
+++ b/src/ht2-lane-tile.cpp
@@ -0,0 +1,163 @@
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/HeaderUtil.h"
+
+#define USE_prefix_out
+#define USE_header_format
+#include "htqc/Options.h"
+#include "htqc/App.h"
+
+#include <set>
+
+using namespace std;
+using namespace htqc;
+
+typedef set<int16_t> IntSet;
+typedef vector<int16_t> IntList;
+
+IntList OPT_exclude_lane;
+htio2::Option OPT_exclude_lane_ENTRY("lane", 'L', "Filter Options",
+ &OPT_exclude_lane, htio2::Option::FLAG_MULTI_KEY, htio2::ValueLimit::Free(),
+ "Unwanted lanes.", "LANE1 [LANE2 ...]");
+
+IntList OPT_exclude_tile;
+htio2::Option OPT_exclude_tile_ENTRY("tile", 'T', "Filter Options",
+ &OPT_exclude_tile, htio2::Option::FLAG_MULTI_KEY, htio2::ValueLimit::Free(),
+ "Unwanted tiles.", "TILE1 [TILE2 ...]");
+
+string OPT_prefix_reject;
+htio2::Option OPT_prefix_reject_ENTRY("reject", 'u', OPTION_GROUP_IO,
+ &OPT_prefix_reject, htio2::Option::FLAG_NONE,
+ "File prefix for rejected sequences.", "FILE_PREFIX");
+
+
+void parse_options(int argc, char **argv)
+{
+ htio2::OptionParser opt_psr;
+
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+ opt_psr.add_option(OPT_prefix_reject_ENTRY);
+
+ opt_psr.add_option(OPT_exclude_lane_ENTRY);
+ opt_psr.add_option(OPT_exclude_tile_ENTRY);
+
+ opt_psr.add_option(OPT_header_format_ENTRY);
+ opt_psr.add_option(OPT_header_sra_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ // show help
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - filter sequences from specific lane-tile"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_prefix_out();
+ ensure_header_format();
+
+ tidy_prefix_out(OPT_prefix_reject);
+ if (OPT_prefix_out == OPT_prefix_reject)
+ {
+ cerr << "ERROR: conflict output prefix for accepted and rejected reads: " << OPT_prefix_out << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (OPT_exclude_tile.size() == 0)
+ {
+ cerr << "ERROR: tiles to exclude not specified" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_options()
+{
+ show_files_in();
+ show_prefix_out();
+ cout << "# output prefix for rejected sequences: " << OPT_prefix_reject << endl;
+
+ cout << "# exclude lanes: " << endl
+ << "# ";
+ for (size_t i = 0; i < OPT_exclude_lane.size(); i++)
+ {
+ if (i != 0) cout << ", ";
+ cout << OPT_exclude_lane[i];
+ }
+ cout << endl;
+
+ cout << "# wanted tiles: " << endl
+ << "# ";
+ for (size_t i = 0; i < OPT_exclude_tile.size(); i++)
+ {
+ if (i != 0) cout << ", ";
+ cout << OPT_exclude_tile[i];
+ }
+ cout << endl;
+}
+
+void execute()
+{
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ htio2::FastqIO fh_out(file_out, htio2::WRITE, OPT_compress);
+
+ htio2::FastqIO::Ptr fh_reject;
+ if (OPT_prefix_reject.length())
+ {
+ string file_reject;
+ add_fastq_suffix_se(OPT_prefix_reject, OPT_compress, file_reject);
+ fh_reject = new htio2::FastqIO(file_reject, htio2::WRITE, OPT_compress);
+ }
+
+ IntSet lane_search(OPT_exclude_lane.begin(), OPT_exclude_lane.end());
+ IntSet tile_search(OPT_exclude_tile.begin(), OPT_exclude_tile.end());
+
+ htio2::HeaderParser header_parser(OPT_header_format, OPT_header_sra);
+
+ htio2::FastqSeq seq;
+ size_t n_process = 0;
+ size_t n_accept = 0;
+ for (size_t i_file = 0; i_file < OPT_files_in.size(); i_file++)
+ {
+ htio2::FastqIO fh_in(OPT_files_in[i_file], htio2::READ, OPT_compress);
+
+ while (fh_in.next_seq(seq))
+ {
+ n_process++;
+ header_parser.parse(seq.id, seq.desc);
+
+ if ((lane_search.empty() || lane_search.count(header_parser.lane)) &&
+ tile_search.count(header_parser.tile))
+ {
+ if (fh_reject)
+ fh_reject->write_seq(seq);
+ }
+ else
+ {
+ fh_out.write_seq(seq);
+ n_accept++;
+ }
+
+ if (!OPT_quiet and (n_process%LOG_BLOCK == 0))
+ cout << " " << n_process << " reads, " << n_accept << " accept" << endl;
+ }
+ }
+
+ if (!OPT_quiet)
+ cout << " " << n_process << " reads, " << n_accept << " accept" << endl;
+}
diff --git a/src/ht2-overlap.cpp b/src/ht2-overlap.cpp
new file mode 100644
index 0000000..b0c5400
--- /dev/null
+++ b/src/ht2-overlap.cpp
@@ -0,0 +1,255 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "htio2/FastqIO.h"
+#include "htio2/QualityUtil.h"
+
+#define USE_prefix_out
+#define USE_encode
+#define USE_se_pe
+#define USE_interleave
+#include "htqc/Options.h"
+#include "htqc/MicroAssembler.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+// we need to process reads in fwd strand
+#define PE_STRAND_FILE OPT_pe_strand1(), OPT_pe_strand2()
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_FWD
+
+using namespace std;
+using namespace htqc;
+
+string OPT_prefix_reject;
+htio2::Option OPT_prefix_reject_ENTRY("reject", 'u', OPTION_GROUP_IO,
+ &OPT_prefix_reject, htio2::Option::FLAG_NONE,
+ "Output file prefix for non-overlapping reads.",
+ "FILE_PREFIX");
+
+#define OPTION_GROUP_PARAM "Overlapping Parameters"
+size_t OPT_word_size = 7;
+htio2::Option OPT_word_size_ENTRY("word-size", 'W', OPTION_GROUP_PARAM,
+ &OPT_word_size, htio2::Option::FLAG_NONE,
+ "Alignment is initiated from identical bases of this length.",
+ "INT");
+
+int16_t OPT_conf_qual = 20;
+htio2::Option OPT_conf_qual_ENTRY("quality", 'Q', OPTION_GROUP_PARAM,
+ &OPT_conf_qual, htio2::Option::FLAG_NONE,
+ "Only the bases whose quality is higher than this are used for kmer generation and identity counting.",
+ "INT");
+
+size_t OPT_iden = 10;
+htio2::Option OPT_iden_ENTRY("match", 'M', OPTION_GROUP_PARAM,
+ &OPT_iden, htio2::Option::FLAG_NONE,
+ "Number of matched bases required for assembly.",
+ "INT");
+
+int16_t OPT_qual_diff = 15;
+htio2::Option OPT_qual_diff_ENTRY("quality-diff", 'D', OPTION_GROUP_PARAM,
+ &OPT_qual_diff, htio2::Option::FLAG_NONE,
+ "Quality difference to accept mismatches.",
+ "INT");
+
+void parse_options(int argc, char** argv)
+{
+ // we are always processing PE
+ OPT_pe = true;
+
+ htio2::OptionParser opt_psr;
+
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+ opt_psr.add_option(OPT_prefix_reject_ENTRY);
+
+ opt_psr.add_option(OPT_pe_itlv_ENTRY);
+ opt_psr.add_option(OPT_pe_strand_ENTRY);
+ opt_psr.add_option(OPT_encode_ENTRY);
+ opt_psr.add_option(OPT_mask_ENTRY);
+
+ opt_psr.add_option(OPT_word_size_ENTRY);
+ opt_psr.add_option(OPT_conf_qual_ENTRY);
+ opt_psr.add_option(OPT_iden_ENTRY);
+ opt_psr.add_option(OPT_qual_diff_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ //
+ // show help
+ //
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - assemble paired-ends into single sequences"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_se_pe();
+ ensure_encode();
+ ensure_prefix_out();
+
+ tidy_prefix_out(OPT_prefix_reject);
+}
+
+void show_options()
+{
+ show_files_in();
+ show_prefix_out();
+ if (OPT_prefix_reject.length())
+ cout << "# file prefix for non-assembled reads: " << OPT_prefix_reject << endl;
+ show_encode();
+ cout << "# assembly parameters:" << endl;
+ cout << "# kmer size: " << OPT_word_size << endl;
+ cout << "# quality for confidental bases: " << OPT_conf_qual << endl;
+ cout << "# quality difference for acceptable conflict bases: " << OPT_qual_diff << endl;
+ cout << "# required number of identical bases: " << OPT_iden << endl;
+}
+
+size_t n_seq = 0;
+size_t n_asm = 0;
+
+void process_one(const htio2::FastqSeq& seq1,
+ const htio2::FastqSeq& seq2,
+ htio2::SeqIO& fh_asm,
+ htio2::PairedEndIO* fh_nasm,
+ htqc::MicroAssembler& assembler)
+{
+ n_seq++;
+
+ vector<int16_t> qual_a;
+ vector<int16_t> qual_b;
+ htio2::decode_quality(seq1.quality, qual_a, OPT_encode);
+ htio2::decode_quality(seq2.quality, qual_b, OPT_encode);
+
+ htio2::FastqSeq result;
+
+ bool re = assembler.assemble(seq1.seq, qual_a, seq2.seq, qual_b);
+
+ if (re)
+ {
+ result.id = seq1.id;
+ result.desc = assembler.result_desc;
+ result.seq = assembler.result_seq;
+ htio2::encode_quality(assembler.result_qual, result.quality, OPT_encode);
+ fh_asm.write_seq(result);
+ n_asm++;
+ }
+ else if (fh_nasm)
+ {
+ fh_nasm->write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+
+ if (!OPT_quiet && n_seq % LOG_BLOCK == 0)
+ cout << " " << n_seq << " pairs, " << n_asm << " assembled" << endl;
+}
+
+void execute()
+{
+ // output handle
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ htio2::SeqIO::Ptr o_merge(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+
+ // handle for non-overlap reads
+ htio2::PairedEndIO* o_fail = NULL;
+
+ if (OPT_prefix_reject.length())
+ {
+ if (OPT_pe_itlv)
+ {
+ // generate file name for non-overlap reads
+ string file_u;
+ add_fastq_suffix_se(OPT_prefix_reject, OPT_compress, file_u);
+ check_output_overwrite(OPT_files_in, file_u);
+
+ // create handle
+ o_fail = new htio2::PairedEndIO(file_u,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+ else
+ {
+ // generate file name for non-overlap reads
+ string file_u1;
+ string file_u2;
+ add_fastq_suffix_pe(OPT_prefix_reject, OPT_compress, file_u1, file_u2);
+ check_output_overwrite(OPT_files_in, file_u1);
+ check_output_overwrite(OPT_files_in, file_u2);
+
+ // create handle
+ o_fail = new htio2::PairedEndIO(file_u1,
+ file_u2,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+ }
+
+ // traverse input
+ MicroAssembler assembler(OPT_word_size,
+ OPT_conf_qual,
+ OPT_iden,
+ OPT_qual_diff);
+
+ if (!OPT_quiet)
+ cout << "beginning assembly" << endl;
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ if (OPT_pe_itlv)
+ {
+ htqc::MultiSeqFilePE fh_in(OPT_files_in,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ while (fh_in.next_pair(seq1, seq2, PE_STRAND_OBJ))
+ process_one(seq1, seq2, *o_merge, o_fail, assembler);
+ }
+ else
+ {
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+
+ htqc::MultiSeqFilePE fh_in(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ while (fh_in.next_pair(seq1, seq2, PE_STRAND_OBJ))
+ process_one(seq1, seq2, *o_merge, o_fail, assembler);
+ }
+
+ if (!OPT_quiet)
+ cout << " " << n_seq << " pairs, " << n_asm << " assembled" << endl;
+
+ if (o_fail)
+ delete o_fail;
+}
diff --git a/src/ht2-primer-trim.cpp b/src/ht2-primer-trim.cpp
new file mode 100644
index 0000000..2a5fcb1
--- /dev/null
+++ b/src/ht2-primer-trim.cpp
@@ -0,0 +1,690 @@
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/PairedEndIO.h"
+#include "htio2/Kmer.h"
+#include "htio2/FastaIO.h"
+#include "htio2/QualityUtil.h"
+
+#define USE_se_pe
+#define USE_encode
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/Primer.h"
+#include "htqc/MultiSeqFile.h"
+
+#include "htio2/JUCE-3.0.8/JuceHeader.h"
+
+// we need paired-end reads in fwd-rev style
+#define PE_STRAND_FILE OPT_pe_strand1(), OPT_pe_strand2()
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_REV
+
+using namespace std;
+using namespace htqc;
+using namespace htio2::juce;
+
+string OPT_dir_out;
+htio2::Option OPT_dir_out_ENTRY("out", 'o', OPTION_GROUP_IO,
+ &OPT_dir_out, htio2::Option::FLAG_NONE,
+ "Output directory.", "DIR");
+
+string OPT_file_primer;
+htio2::Option OPT_file_primer_ENTRY("primer", '\0', OPTION_GROUP_IO,
+ &OPT_file_primer, htio2::Option::FLAG_NONE,
+ "Primers in FASTA format. IDs of left primers should begin with \"left\", and IDs for right primers should begin with \"right\".",
+ "FILE");
+
+#define OPTION_GROUP_ALGO "Primer Trimming Parameters"
+bool OPT_no_revcom;
+htio2::Option OPT_no_revcom_ENTRY("no-revcom", '\0', OPTION_GROUP_ALGO,
+ &OPT_no_revcom, htio2::Option::FLAG_NONE,
+ "Do not check primers in reverse complement strand.");
+
+bool OPT_no_trim;
+htio2::Option OPT_no_trim_ENTRY("no-trim", '\0', OPTION_GROUP_ALGO,
+ &OPT_no_trim, htio2::Option::FLAG_NONE,
+ "Pick primer-containing reads and do not trim primer.");
+
+int OPT_mismatch_high = 3;
+htio2::Option OPT_mismatch_high_ENTRY("mismatch-high", '\0', OPTION_GROUP_ALGO,
+ &OPT_mismatch_high, htio2::Option::FLAG_NONE,
+ "Allowed number of mismatches on high-quality bases.",
+ "INT");
+
+int OPT_mismatch = 6;
+htio2::Option OPT_mismatch_ENTRY("mismatch", '\0', OPTION_GROUP_ALGO,
+ &OPT_mismatch, htio2::Option::FLAG_NONE,
+ "Allowed number of mismatches.",
+ "INT");
+
+int OPT_tail_miss = 5;
+htio2::Option OPT_tail_miss_ENTRY("tail-miss", '\0', OPTION_GROUP_ALGO,
+ &OPT_tail_miss, htio2::Option::FLAG_NONE,
+ "Allowed length of missing bases on primer 5'-end.",
+ "INT");
+
+int OPT_cut_qual = 10;
+htio2::Option OPT_cut_qual_ENTRY("cut-qual", '\0', OPTION_GROUP_ALGO,
+ &OPT_cut_qual, htio2::Option::FLAG_NONE,
+ "Quality cutoff.",
+ "INT");
+
+
+
+// primer data
+typedef map<string, PrimerGroup> AllPrimerType;
+AllPrimerType primers;
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser opt_psr;
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_dir_out_ENTRY);
+ opt_psr.add_option(OPT_file_primer_ENTRY);
+
+ opt_psr.add_option(OPT_se_ENTRY);
+ opt_psr.add_option(OPT_pe_ENTRY);
+ opt_psr.add_option(OPT_pe_itlv_ENTRY);
+ opt_psr.add_option(OPT_pe_strand_ENTRY);
+ opt_psr.add_option(OPT_encode_ENTRY);
+ opt_psr.add_option(OPT_mask_ENTRY);
+
+ opt_psr.add_option(OPT_no_revcom_ENTRY);
+ opt_psr.add_option(OPT_no_trim_ENTRY);
+ opt_psr.add_option(OPT_cut_qual_ENTRY);
+ opt_psr.add_option(OPT_tail_miss_ENTRY);
+ opt_psr.add_option(OPT_mismatch_ENTRY);
+ opt_psr.add_option(OPT_mismatch_high_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ // show help
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - remove primer sequence from reads"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version)
+ show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_se_pe();
+ ensure_encode();
+
+ if (!OPT_dir_out.length())
+ {
+ cerr << "ERROR: output directory not specified!" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (!OPT_file_primer.length())
+ {
+ cerr << "ERROR: primer file not specified!" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ cout << "# output dir: " << OPT_dir_out << endl;
+ cout << "# primers: " << OPT_file_primer << endl;
+ cout << "# allowed mismatch for high-quality bases: " << OPT_mismatch_high << endl;
+ cout << "# allowed mismatch: " << OPT_mismatch << endl;
+ cout << "# cutoff for low-quality bases: " << OPT_cut_qual << endl;
+ show_encode();
+}
+
+size_t kmer_size = 0;
+
+void read_primers()
+{
+ // first pass
+ // find minimum length
+ size_t min_len = 65535;
+ {
+ htio2::FastaIO IN(OPT_file_primer, htio2::READ);
+ htio2::SimpleSeq seq;
+
+ while (IN.next_seq(seq))
+ {
+ if (seq.seq.length() < min_len)
+ min_len = seq.seq.length();
+ }
+ }
+
+ // calculate kmer size
+ kmer_size = (min_len - OPT_mismatch_high) / (OPT_mismatch_high + 1);
+ if (kmer_size < 4) kmer_size = 4;
+ if (!OPT_quiet) cout << " shortest primer: " << min_len << ", alignment kmer size: " << kmer_size << endl;
+
+ // read primers
+ htio2::FastaIO IN(OPT_file_primer, htio2::READ);
+ htio2::SimpleSeq seq;
+
+ if (!OPT_quiet)cout << "read primers" << endl;
+ while (IN.next_seq(seq))
+ {
+ if (!seq.desc.length())
+ {
+ cerr << "primer \"" << seq.id << "\" has no description" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // find or create the corresponding primer group
+ AllPrimerType::iterator primer_map_i = primers.find(seq.desc);
+ if (primer_map_i == primers.end())
+ primer_map_i = primers.insert(make_pair(seq.desc, PrimerGroup(seq.desc))).first;
+ PrimerGroup& primer_group = primer_map_i->second;
+
+ // add primer to primer group
+ if (seq.id.find("left") == 0)
+ primer_group.primers_left.push_back(Primer(seq.id, seq.seq, kmer_size));
+ else if (seq.id.find("right") == 0)
+ primer_group.primers_right.push_back(Primer(seq.id, seq.seq, kmer_size));
+ else
+ {
+ cerr << "ERROR: primer file has sequence with invalid ID: " << seq.id << endl
+ << "IDs must begin with \"left\" or \"right\"" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // check primer number
+ if (!OPT_quiet)
+ cout << " " << primers.size() << " primer groups" << endl;
+
+ for (AllPrimerType::const_iterator i = primers.begin(); i != primers.end(); ++i)
+ {
+ const PrimerGroup& group = i->second;
+
+ if (!group.primers_left.size())
+ {
+ cerr << "ERROR: group " << group.name << " has no left primer" << endl;
+ exit (EXIT_FAILURE);
+ }
+
+ if (!group.primers_right.size())
+ {
+ cerr << "ERROR: group " << group.name << " has no right primer" << endl;
+ exit (EXIT_FAILURE);
+ }
+
+ if (!OPT_quiet)
+ cout << " " << group.name << " left " << group.primers_left.size() << ", right " << group.primers_right.size() << endl;
+ }
+}
+
+
+
+#define LEFT_START_OK primer_start <= OPT_tail_miss
+#define LEFT_END_OK primer_end + 1 == curr_primer_len
+#define RIGHT_START_OK primer_start == 0
+#define RIGHT_END_OK curr_primer_len - primer_end - 1 <= OPT_tail_miss
+
+size_t n_seq = 0;
+size_t n_accept = 0;
+
+void trim_se()
+{
+ // create output file handles
+ map<string, htio2::SeqIO::Ptr> fh_out_map;
+ for (map<string, PrimerGroup>::const_iterator i = primers.begin(); i != primers.end(); i++)
+ {
+ const string& name = i->first;
+ File prefix_out = File(OPT_dir_out).getChildFile(String(name));
+ string file_out;
+ add_fastq_suffix_se(prefix_out.getFullPathName().toStdString(), OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+
+ htio2::SeqIO::Ptr fh_out(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+ fh_out_map.insert(make_pair(name, fh_out));
+ }
+
+ // create file handle for failed ones
+ htio2::SeqIO::Ptr fh_fail(0);
+ {
+ File prefix_fail = File(OPT_dir_out).getChildFile("PRIMER_FAIL");
+ string file_fail;
+ add_fastq_suffix_se(prefix_fail.getFullPathName().toStdString(), OPT_compress, file_fail);
+ check_output_overwrite(OPT_files_in, file_fail);
+ fh_fail = htio2::SeqIO::New(file_fail, htio2::WRITE, OPT_compress);
+ }
+
+ // traverse input
+ htio2::FastqSeq curr_seq;
+ htio2::EncodedSeq curr_enc;
+ KmerList curr_kmer;
+ vector<int16_t> curr_qual;
+
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ while (fh_in.next_seq(curr_seq))
+ {
+ n_seq++;
+
+ // preprocess current read
+ htio2::encode_nt5(curr_seq.seq, curr_enc);
+ htio2::gen_kmer_nt5(curr_enc, curr_kmer, kmer_size);
+ htio2::decode_quality(curr_seq.quality, curr_qual, OPT_encode);
+
+ // traverse primer groups
+ bool matched = false;
+
+ for (AllPrimerType::const_iterator i = primers.begin(); i != primers.end(); i++)
+ {
+ const string& primer_group_name = i->first;
+ const PrimerGroup& primer_group = i->second;
+
+ PosT read_start = 0;
+ PosT read_end = 0;
+ PosT primer_start = 0;
+ PosT primer_end = 0;
+
+ bool left_fwd_ok = false;
+ bool right_fwd_ok = false;
+ bool left_rev_ok = false;
+ bool right_rev_ok = false;
+ PosT trim_fwd_from = 0;
+ PosT trim_fwd_to = 0;
+ PosT trim_rev_from = 0;
+ PosT trim_rev_to = 0;
+
+ //
+ // compare with primers
+ //
+
+ size_t num_left = primer_group.primers_left.size();
+ size_t num_right = primer_group.primers_right.size();
+
+ // left primer
+ for (size_t i = 0; i < num_left; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_left[i].length();
+ bool aligned = primer_group.primers_left[i].align_fwd(curr_seq.seq, curr_qual, curr_kmer,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ left_fwd_ok = true;
+ trim_fwd_from = read_end + 1;
+ break;
+ }
+ }
+
+ // right primer revcom
+ for (size_t i = 0; i < num_right; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_right[i].length();
+ bool aligned = primer_group.primers_right[i].align_rev(curr_seq.seq, curr_qual, curr_kmer,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ if (aligned && RIGHT_START_OK && RIGHT_END_OK)
+ {
+ right_fwd_ok = true;
+ trim_fwd_to = read_start - 1;
+ break;
+ }
+ }
+
+ // compare with reverse complement strand
+ if (!OPT_no_revcom)
+ {
+ // right primer
+ for (size_t i = 0; i < num_right; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_right[i].length();
+ bool aligned = primer_group.primers_right[i].align_fwd(curr_seq.seq, curr_qual, curr_kmer,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ // aligned on left, using left rules
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ right_rev_ok = true;
+ trim_rev_from = read_end + 1;
+ break;
+ }
+ }
+
+ // left primer revcom
+ for (size_t i = 0; i < num_left; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_left[i].length();
+ bool aligned = primer_group.primers_left[i].align_rev(curr_seq.seq, curr_qual, curr_kmer,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ // aligned on right, using right rules
+ if (aligned && RIGHT_START_OK && RIGHT_END_OK)
+ {
+ left_rev_ok = true;
+ trim_rev_to = read_start - 1;
+ break;
+ }
+ }
+ }
+
+ // write output
+ if ((!num_left || left_fwd_ok) && (!num_right || right_fwd_ok))
+ {
+ n_accept++;
+ matched = true;
+ if (OPT_no_trim)
+ {
+ fh_out_map[primer_group_name]->write_seq(curr_seq);
+ }
+ else
+ {
+ htio2::FastqSeq trimmed_seq;
+ curr_seq.subseq(trimmed_seq, trim_fwd_from, trim_fwd_to - trim_fwd_from + 1);
+ fh_out_map[primer_group_name]->write_seq(trimmed_seq);
+ }
+ }
+ else if ((!num_left || left_rev_ok) && (!num_right || right_rev_ok))
+ {
+ n_accept++;
+ matched = true;
+ if (OPT_no_trim)
+ {
+ fh_out_map[primer_group_name]->write_seq(curr_seq);
+ }
+ else
+ {
+ htio2::FastqSeq trimmed_seq;
+ curr_seq.subseq(trimmed_seq, trim_rev_from, trim_rev_to - trim_rev_from + 1);
+ fh_out_map[primer_group_name]->write_seq(trimmed_seq);
+ }
+ }
+
+ if (matched) break;
+ } // primer group cycle
+
+ if (!matched)
+ fh_fail->write_seq(curr_seq);
+
+ if (!OPT_quiet && n_seq % LOG_BLOCK == 0)
+ cout << " " << n_seq << " reads, " << n_accept << " trimmed" << endl;
+ } // sequence cycle
+
+
+ if (!OPT_quiet)
+ cout << "done: " << n_seq << " reads, " << n_accept << " trimmed" << endl;
+}
+
+void do_one_pe(const htio2::FastqSeq& seq1,
+ const htio2::FastqSeq& seq2,
+ map<string, htio2::PairedEndIO::Ptr>& fh_out,
+ htio2::PairedEndIO* fh_fail)
+{
+ n_seq++;
+
+ static htio2::EncodedSeq enc1;
+ static htio2::EncodedSeq enc2;
+ static KmerList klist1;
+ static KmerList klist2;
+ static vector<int16_t> qlist1;
+ static vector<int16_t> qlist2;
+
+ PosT read_start = 0;
+ PosT read_end = 0;
+ PosT primer_start = 0;
+ PosT primer_end = 0;
+
+ bool left_fwd_ok = false;
+ bool right_fwd_ok = false;
+ bool left_rev_ok = false;
+ bool right_rev_ok = false;
+ PosT trim_fwd_r1 = 0;
+ PosT trim_fwd_r2 = 0;
+ PosT trim_rev_r1 = 0;
+ PosT trim_rev_r2 = 0;
+
+ // preprocess current read
+ htio2::encode_nt5(seq1.seq, enc1);
+ htio2::encode_nt5(seq2.seq, enc2);
+ htio2::gen_kmer_nt5(enc1, klist1, kmer_size);
+ htio2::gen_kmer_nt5(enc2, klist2, kmer_size);
+ htio2::decode_quality(seq1.quality, qlist1, OPT_encode);
+ htio2::decode_quality(seq2.quality, qlist2, OPT_encode);
+
+ // traverse primer groups
+ bool matched = false;
+ for (AllPrimerType::const_iterator i = primers.begin(); i != primers.end(); i++)
+ {
+ const string& primer_group_name = i->first;
+ const PrimerGroup& primer_group = i->second;
+
+ size_t n_primer_left = primer_group.primers_left.size();
+ size_t n_primer_right = primer_group.primers_right.size();
+
+ // left on read 1
+ for (size_t i = 0; i < n_primer_left; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_left[i].length();
+ bool aligned = primer_group.primers_left[i].align_fwd(seq1.seq, qlist1, klist1,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ left_fwd_ok = true;
+ trim_fwd_r1 = read_end + 1;
+ break;
+ }
+ }
+
+ // right on read 2
+ for (size_t i = 0; i < n_primer_right; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_right[i].length();
+ bool aligned = primer_group.primers_right[i].align_fwd(seq2.seq, qlist2, klist2,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ right_fwd_ok = true;
+ trim_fwd_r2 = read_end + 1;
+ break;
+ }
+ }
+
+ // revcom
+ if (!OPT_no_revcom)
+ {
+ // align right revcom on read 1
+ for (size_t i = 0; i < n_primer_right; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_right[i].length();
+ bool aligned = primer_group.primers_right[i].align_rev(seq1.seq, qlist1, klist1,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ right_rev_ok = true;
+ trim_rev_r1 = read_end + 1;
+ break;
+ }
+ }
+
+ // align left revcom on read 2
+ for (size_t i = 0; i < n_primer_left; i++)
+ {
+ const size_t curr_primer_len = primer_group.primers_left[i].length();
+ bool aligned = primer_group.primers_left[i].align_rev(seq2.seq, qlist2, klist2,
+ OPT_cut_qual, OPT_mismatch_high, OPT_mismatch,
+ read_start, read_end, primer_start, primer_end);
+ if (aligned && LEFT_START_OK && LEFT_END_OK)
+ {
+ left_rev_ok = true;
+ trim_rev_r2 = read_end + 1;
+ break;
+ }
+ }
+
+ }
+
+ // fwd ok
+ if ((!n_primer_left || left_fwd_ok)
+ &&
+ (!n_primer_right || right_fwd_ok))
+ {
+ n_accept++;
+ matched = true;
+ if (OPT_no_trim)
+ {
+ fh_out[primer_group_name]->write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+ else
+ {
+ htio2::FastqSeq trimmed1;
+ htio2::FastqSeq trimmed2;
+ seq1.subseq(trimmed1, trim_fwd_r1);
+ seq2.subseq(trimmed2, trim_fwd_r2);
+ fh_out[primer_group_name]->write_pair(trimmed1, trimmed2, PE_STRAND_OBJ);
+ }
+ }
+ // revcom ok
+ else if ((!n_primer_left || left_rev_ok)
+ &&
+ (!n_primer_right || right_rev_ok))
+ {
+ n_accept++;
+ matched = true;
+ if (OPT_no_trim)
+ {
+ fh_out[primer_group_name]->write_pair(seq1, seq2, PE_STRAND_OBJ);
+ }
+ else
+ {
+ htio2::FastqSeq trimmed1;
+ htio2::FastqSeq trimmed2;
+ seq1.subseq(trimmed1, trim_rev_r1);
+ seq2.subseq(trimmed2, trim_rev_r2);
+ fh_out[primer_group_name]->write_pair(trimmed1, trimmed2, PE_STRAND_OBJ);
+ }
+ }
+
+ if (matched)
+ break;
+ }
+
+ if (!matched)
+ fh_fail->write_pair(seq1, seq2);
+
+ if (!OPT_quiet && n_seq % LOG_BLOCK == 0)
+ cout << " " << n_seq << " pairs, " << n_accept << " trimmed" << endl;
+}
+
+void trim_pe()
+{
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ // output handles
+ map<string, htio2::PairedEndIO::Ptr> fh_out_map;
+ for (map<string, PrimerGroup>::const_iterator i = primers.begin(); i != primers.end(); i++)
+ {
+ const string& name = i->first;
+ File prefix_out = File(OPT_dir_out).getChildFile(String(name));
+
+ if (OPT_pe_itlv)
+ {
+ string file_out;
+ add_fastq_suffix_se(prefix_out.getFullPathName().toStdString(), OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+
+ htio2::PairedEndIO::Ptr fh(new htio2::PairedEndIO(file_out, htio2::WRITE, PE_STRAND_FILE, OPT_compress));
+ fh_out_map.insert(make_pair(name, fh));
+ }
+ else
+ {
+ string file_out1;
+ string file_out2;
+ add_fastq_suffix_pe(prefix_out.getFullPathName().toStdString(), OPT_compress, file_out1, file_out2);
+ check_output_overwrite(OPT_files_in, file_out1);
+ check_output_overwrite(OPT_files_in, file_out2);
+
+ htio2::PairedEndIO::Ptr fh(new htio2::PairedEndIO(file_out1, file_out2, htio2::WRITE, PE_STRAND_FILE, OPT_compress));
+ fh_out_map.insert(make_pair(name, fh));
+ }
+ }
+
+ // handle for negative reads
+ htio2::PairedEndIO::Ptr fh_fail;
+ {
+ File prefix_fail = File(OPT_dir_out).getChildFile("PRIMER_FAIL");
+ if (OPT_pe_itlv)
+ {
+ string file_fail;
+ add_fastq_suffix_se(prefix_fail.getFullPathName().toStdString(), OPT_compress, file_fail);
+ check_output_overwrite(OPT_files_in, file_fail);
+ fh_fail = new htio2::PairedEndIO(file_fail, htio2::WRITE, PE_STRAND_FILE, OPT_compress);
+ }
+ else
+ {
+ string file_fail1;
+ string file_fail2;
+ add_fastq_suffix_pe(prefix_fail.getFullPathName().toStdString(), OPT_compress, file_fail1, file_fail2);
+ check_output_overwrite(OPT_files_in, file_fail1);
+ check_output_overwrite(OPT_files_in, file_fail2);
+
+ fh_fail = new htio2::PairedEndIO(file_fail1, file_fail2, htio2::WRITE, PE_STRAND_FILE, OPT_compress);
+ }
+ }
+
+ // input handle
+ htqc::MultiSeqFilePE* fh_in;
+ if (OPT_pe_itlv)
+ {
+ fh_in = new htqc::MultiSeqFilePE(OPT_files_in, PE_STRAND_FILE, OPT_compress);
+ }
+ else
+ {
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+ fh_in = new htqc::MultiSeqFilePE(files_in_a, files_in_b, PE_STRAND_FILE, OPT_compress);
+ }
+
+ // traverse input file pairs
+ while (fh_in->next_pair(seq1, seq2, PE_STRAND_OBJ))
+ do_one_pe(seq1, seq2, fh_out_map, fh_fail.get());
+
+ delete fh_in;
+
+ if (!OPT_quiet)
+ cout << "done: " << n_seq << " pairs, " << n_accept << " trimmed" << endl;
+}
+
+void execute()
+{
+ read_primers();
+
+ File dir_out_obj(OPT_dir_out);
+ if (!dir_out_obj.isDirectory())
+ {
+ Result re = dir_out_obj.createDirectory();
+ if (re.failed())
+ {
+ fprintf(stderr, "ERROR: failed to create output directory \"%s\": %s\n",
+ OPT_dir_out.c_str(), re.getErrorMessage().toRawUTF8());
+ }
+ }
+
+ if (OPT_se)
+ trim_se();
+ else if (OPT_pe)
+ trim_pe();
+ else
+ throw runtime_error("neither single-end nor paired-end");
+}
diff --git a/src/ht2-rename.cpp b/src/ht2-rename.cpp
new file mode 100644
index 0000000..c5b6606
--- /dev/null
+++ b/src/ht2-rename.cpp
@@ -0,0 +1,114 @@
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+
+#define USE_prefix_out
+#define USE_se_pe
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+#include <sstream>
+
+using namespace std;
+using namespace htqc;
+
+#define OPTION_GROUP_NAMING "Naming Options"
+
+string OPT_name_prefix;
+htio2::Option OPT_name_prefix_ENTRY("prefix", '\0', OPTION_GROUP_NAMING,
+ &OPT_name_prefix, htio2::Option::FLAG_NONE,
+ "Prefix for generated IDs.", "STRING");
+
+string OPT_name_suffix;
+htio2::Option OPT_name_suffix_ENTRY("suffix", '\0', OPTION_GROUP_NAMING,
+ &OPT_name_suffix, htio2::Option::FLAG_NONE,
+ "Suffix for generated IDs.", "STRING");
+
+bool keep_desc;
+htio2::Option OPT_keep_desc_ENTRY("keep-desc", '\0', OPTION_GROUP_NAMING,
+ &keep_desc, htio2::Option::FLAG_NONE,
+ "Keep description of the input sequences, which is the header content after first continuous blank.");
+
+void parse_options(int argc, char** argv)
+{
+ OPT_se = true;
+
+ htio2::OptionParser opt_psr;
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+
+ opt_psr.add_option(OPT_name_prefix_ENTRY);
+ opt_psr.add_option(OPT_name_suffix_ENTRY);
+ opt_psr.add_option(OPT_keep_desc_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ //
+ // show help
+ //
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - generate simple sequence IDs by batch"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_prefix_out();
+
+ if (OPT_name_prefix.length() == 0 && OPT_name_suffix.length() == 0)
+ cerr << "WARNING: neither prefix nor suffix was provided!" << endl;
+}
+
+void show_options()
+{
+ show_files_in();
+ show_prefix_out();
+ cout << "# ID format: " << OPT_name_prefix << "(NUMBER)" << OPT_name_suffix;
+ if (keep_desc) cout << " DESCRIPTION";
+ cout << endl;
+}
+
+void execute()
+{
+ // output handle
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ htio2::SeqIO::Ptr fh_out(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+
+ // traverse input files
+ if (!OPT_quiet) cout << "process sequences" << endl;
+ size_t num_seq = 0;
+ htio2::FastqSeq curr_seq;
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ while (fh_in.next_seq(curr_seq))
+ {
+ num_seq++;
+ if (!OPT_quiet && num_seq % LOG_BLOCK == 0)
+ cout << " " << num_seq << " sequences processed" << endl;
+
+ ostringstream id_new;
+ id_new << OPT_name_prefix << num_seq << OPT_name_suffix;
+
+ curr_seq.id = id_new.str();
+ if (!keep_desc)
+ curr_seq.desc = "";
+
+ fh_out->write_seq(curr_seq);
+ }
+
+ if (!OPT_quiet) cout << " " << num_seq << " sequences processed" << endl;
+}
diff --git a/src/ht2-sample.cpp b/src/ht2-sample.cpp
new file mode 100644
index 0000000..7a48eff
--- /dev/null
+++ b/src/ht2-sample.cpp
@@ -0,0 +1,404 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/PairedEndIO.h"
+
+#define USE_prefix_out
+#define USE_se_pe
+#define USE_interleave
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+#include "htio2/MT19937.h"
+
+#include <set>
+#include <iostream>
+#include <fstream>
+
+// We don't care strand in this program, so simply let FILE and OBJ to be identical.
+#define PE_STRAND_FILE htio2::STRAND_FWD, htio2::STRAND_FWD
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_FWD
+
+using namespace std;
+using namespace htqc;
+using namespace htio2::juce;
+
+#define OPTION_GROUP_SAMPLING "Sampling Parameters"
+
+double OPT_rate = 0;
+htio2::Option OPT_rate_ENTRY("rate", 'r', OPTION_GROUP_SAMPLING,
+ &OPT_rate, htio2::Option::FLAG_NONE,
+ "1/rate of total reads will be picked.", "NUMBER");
+
+size_t OPT_num = 0;
+htio2::Option OPT_num_ENTRY("num", 'n', OPTION_GROUP_SAMPLING,
+ &OPT_num, htio2::Option::FLAG_NONE,
+ "Number of reads to be picked.", "INT");
+
+int64_t OPT_seed = 0;
+htio2::Option OPT_seed_ENTRY("seed", '\0', OPTION_GROUP_SAMPLING,
+ &OPT_seed, htio2::Option::FLAG_NONE,
+ "Seed for random number generator. 0 to use system-random seed.", "INT");
+
+string OPT_file_out_id;
+htio2::Option OPT_file_out_id_ENTRY("out-id", '\0', OPTION_GROUP_IO,
+ &OPT_file_out_id, htio2::Option::FLAG_NONE,
+ "Write the indices of picked reads to a file. The indices are 0-based.", "FILE");
+
+
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser opt_psr;
+
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+ opt_psr.add_option(OPT_file_out_id_ENTRY);
+
+ opt_psr.add_option(OPT_se_ENTRY);
+ opt_psr.add_option(OPT_pe_ENTRY);
+ opt_psr.add_option(OPT_pe_itlv_ENTRY);
+
+ opt_psr.add_option(OPT_rate_ENTRY);
+ opt_psr.add_option(OPT_num_ENTRY);
+ opt_psr.add_option(OPT_seed_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ //
+ // show help
+ //
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - randomly pick some reads"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_se_pe();
+ ensure_prefix_out();
+
+ if (OPT_rate == 0)
+ {
+ if (OPT_num == 0)
+ {
+ cerr << "ERROR: neither sampling rate nor sampling amount is specified." << endl
+ << "ERROR: you must specify how much to be sampled." << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ if (OPT_num)
+ {
+ cerr << "ERROR: both sampling rate and sampling amount is specified." << endl
+ << "ERROR: you must specify only one of them." << endl;
+ exit(EXIT_FAILURE);
+ }
+ if (OPT_rate <= 1)
+ {
+ cerr << "ERROR: invalid sampling rate: " << OPT_rate << endl
+ << "ERROR: sampling rate must larger than 1" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ show_prefix_out();
+ if (OPT_file_out_id.size())
+ cout << "# output file for used indices: " << OPT_file_out_id << endl;
+
+ if (OPT_rate > 0)
+ cout << "# fraction to be picked: 1/" << OPT_rate << endl;
+ if (OPT_num > 0)
+ cout << "# amount to be picked: " << OPT_num << endl;
+ if (OPT_seed)
+ cout << "# user random seed: " << OPT_seed << endl;
+}
+
+int64_t n_accept = 0;
+int64_t n_input = 0;
+
+int64_t count_se()
+{
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+ htio2::FastqSeq seq;
+ int64_t n = 0;
+
+ while (fh_in.next_seq(seq))
+ n++;
+
+ if (n < 0)
+ {
+ fprintf(stderr, "ERROR: sequence amount overflow!\n");
+ exit(EXIT_FAILURE);
+ }
+ return n;
+}
+
+int64_t count_pe()
+{
+ htqc::MultiSeqFilePE* fh = nullptr;
+ if (OPT_pe_itlv)
+ {
+ fh = new htqc::MultiSeqFilePE(OPT_files_in,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+ else
+ {
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+ fh = new htqc::MultiSeqFilePE(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+ int64_t n = 0;
+
+ while (fh->next_pair(seq1, seq2, PE_STRAND_OBJ))
+ n++;
+
+ if (n < 0)
+ {
+ fprintf(stderr, "ERROR: sequence amount overflow!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ delete fh;
+ return n;
+}
+
+
+
+void shuffle_vector(vector<int64_t>& data, htio2::MT19937& prng)
+{
+ for (size_t i1 = 0; i1 < data.size(); i1++)
+ {
+ uint64_t i2 = prng.next_uint64_in_range(data.size());
+ printf(" switch %lu %lu\n", i1, i2);
+ int64_t tmp = data[i1];
+ data[i1] = data[i2];
+ data[i2] = tmp;
+ }
+}
+
+void rand_pick(int64_t num, set<int64_t>& wanted, htio2::MT19937& prng)
+{
+ vector<int64_t> indices(num);
+ for (int64_t i = 0; i < num; i++)
+ indices[i] = i;
+
+ // shuffle
+ shuffle_vector(indices, prng);
+
+ // do pick
+ size_t n_pick = 0;
+ if (OPT_num)
+ n_pick = OPT_num;
+ else
+ n_pick = indices.size() / OPT_rate;
+
+ for (int i = 0; i < n_pick; i++)
+ {
+ if (!wanted.insert(indices[i]).second)
+ abort();
+ }
+}
+
+void filter_se(const set<int64_t>& wanted)
+{
+ // output handle
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+
+ htio2::SeqIO::Ptr OUT(htio2::SeqIO::New(file_out,
+ htio2::WRITE,
+ OPT_compress));
+
+ // input handle
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ // traverse input sequences
+ htio2::FastqSeq curr_seq;
+ int64_t id = 0;
+
+ while (fh_in.next_seq(curr_seq))
+ {
+ n_input++;
+
+ if (wanted.count(id++))
+ {
+ OUT->write_seq(curr_seq);
+ n_accept++;
+ }
+
+ if (!OPT_quiet && (n_input % LOG_BLOCK == 0))
+ cout << "\t" << n_input << " reads, " << n_accept << " accept" << endl;
+ }
+
+
+
+ if (!OPT_quiet)
+ cout << " " << n_input << " reads, " << n_accept << " accept" << endl;
+}
+
+void filter_pe(const set<int64_t>& wanted)
+{
+ htio2::PairedEndIO* fh_out = NULL;
+ htqc::MultiSeqFilePE* fh_in = NULL;
+
+ if (OPT_pe_itlv)
+ {
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+
+ fh_out = new htio2::PairedEndIO(file_out,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ fh_in = new htqc::MultiSeqFilePE(OPT_files_in,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+ else
+ {
+ string file_out_a;
+ string file_out_b;
+ add_fastq_suffix_pe(OPT_prefix_out, OPT_compress, file_out_a, file_out_b);
+ check_output_overwrite(OPT_files_in, file_out_a);
+ check_output_overwrite(OPT_files_in, file_out_b);
+
+ fh_out = new htio2::PairedEndIO(file_out_a,
+ file_out_b,
+ htio2::WRITE,
+ PE_STRAND_FILE,
+ OPT_compress);
+
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+
+ fh_in = new htqc::MultiSeqFilePE(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+
+ // traverse sequences
+ htio2::FastqSeq curr_seq_a;
+ htio2::FastqSeq curr_seq_b;
+ int64_t id = 0;
+
+ while (fh_in->next_pair(curr_seq_a, curr_seq_b, PE_STRAND_OBJ))
+ {
+ n_input++;
+
+ if (wanted.count(id++))
+ {
+ fh_out->write_pair(curr_seq_a, curr_seq_b, PE_STRAND_OBJ);
+ n_accept++;
+ }
+
+ if (!OPT_quiet && (n_input % LOG_BLOCK == 0))
+ cout << "\t" << n_input << " pairs, " << n_accept << " picked" << endl;
+ }
+
+ delete fh_in;
+ delete fh_out;
+
+ if (!OPT_quiet)
+ cout << " " << n_input << " pairs, " << n_accept << " picked" << endl;
+}
+
+void execute()
+{
+ // init PRNG
+ htio2::MT19937 prng;
+ if (OPT_seed != 0)
+ prng.set_seed(OPT_seed);
+
+ // first pass
+ // get sequence num
+ if (!OPT_quiet)
+ printf("count input sequences\n");
+
+ int64_t num = 0;
+ if (OPT_se)
+ num = count_se();
+ else if (OPT_pe)
+ num = count_pe();
+ else
+ abort();
+
+ if (!OPT_quiet)
+ printf(" %ld total\n", num);
+
+ // generate a table of wanted indices
+ if (!OPT_quiet)
+ printf("randomly generate wanted index table\n");
+ set<int64_t> wanted;
+ rand_pick(num, wanted, prng);
+
+ if (!OPT_quiet)
+ printf(" %lu indices\n", wanted.size());
+
+ // second pass
+ // pick wanted sequences
+ if (OPT_se)
+ filter_se(wanted);
+ else if (OPT_pe)
+ filter_pe(wanted);
+ else
+ abort();
+
+ // write a list of used indices
+ if (OPT_file_out_id.length())
+ {
+ if (!OPT_quiet)
+ printf("write used indices to file \"%s\"\n", OPT_file_out_id.c_str());
+
+ ofstream fh_out_id(OPT_file_out_id.c_str());
+ for (int64_t id : wanted)
+ {
+ fh_out_id << id << endl;
+ }
+ }
+}
diff --git a/src/ht2-stat-draw.pl b/src/ht2-stat-draw.pl
new file mode 100755
index 0000000..c706d15
--- /dev/null
+++ b/src/ht2-stat-draw.pl
@@ -0,0 +1,520 @@
+#!/usr/bin/perl
+
+# HTQC - a high-throughput sequencing quality control toolkit
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+use File::Path;
+use File::Spec::Functions;
+use Chart::Clicker;
+use Getopt::Long;
+
+# output file name base
+my $CYC_QUAL_1 = 'cycle_quality_1';
+my $CYC_QUAL_2 = 'cycle_quality_2';
+my $CYC_QUAL_1_BOX = 'cycle_quality_1.box';
+my $CYC_QUAL_2_BOX = 'cycle_quality_2.box';
+my $READS_QUAL = 'reads_quality';
+my $LANE_TILE_QUAL_1 = 'lane_tile_quality_1';
+my $LANE_TILE_QUAL_2 = 'lane_tile_quality_2';
+my $CYC_COMP_1 = 'cycle_composition_1';
+my $CYC_COMP_2 = 'cycle_composition_2';
+my $UMASK_LEN = 'reads_length';
+my $QUAL_QQ = 'quality_QQ';
+
+my $dir_data;
+my $WIDTH = 600;
+my $HEIGHT = 400;
+my $SZ_TITLE = 12;
+my $SZ_TEXT = 9;
+my $FORMAT = 'pdf';
+
+GetOptions(
+ 'dir=s' => \$dir_data,
+ 'format=s' => \$FORMAT,
+ 'width=s' => \$WIDTH,
+ 'height=s' => \$HEIGHT,
+ 'title-size=s' => \$SZ_TITLE,
+ 'text-size=s' => \$SZ_TEXT,
+ 'help' => \&show_help
+);
+
+#
+# validate dir
+#
+die "data directory not specified" if !defined $dir_data;
+die "data directory not exist" if !-d $dir_data;
+
+my $file_info = catfile $dir_data, 'info.tab';
+die "info file not exist" if !-f $file_info;
+
+#
+# get info
+#
+open INFO, '<', $file_info or die "failed to open info file '$file_info': $!";
+my $PAIRED;
+my $LENGTH;
+my $QUAL_FROM;
+my $QUAL_TO;
+my $MASK;
+
+while (<INFO>) {
+ chomp;
+ my ( $key, $value ) = split /\t/;
+ if ( $key eq 'paired' ) {
+ $PAIRED = $value eq 'T' ? 1 : 0;
+ }
+ elsif ( $key eq 'length' ) {
+ $LENGTH = $value;
+ }
+ elsif ( $key eq 'quality range' ) {
+ $value =~ /^(\d+)-(\d+)$/
+ or die "failed to parse quality range: '$value'";
+ $QUAL_FROM = $1;
+ $QUAL_TO = $2;
+ }
+ elsif ( $key eq 'mask' ) {
+ $MASK = $value eq 'T' ? 1 : 0;
+ }
+}
+
+close INFO;
+
+#
+# test the existence of gnuplot
+#
+my $HAS_GNUPLOT = 1;
+`gnuplot -V`;
+if ( $? != 0 ) {
+ print STDERR <<INFO_GNUPLOT_NOTFOUND;
+Gnuplot is not found in your system. Plot scripts are generated but are not
+rendered.
+Please install Gnuplot using the package management system of your Unix
+distribution, or visit Gnuplot website: http://sourceforge.net/projects/gnuplot
+INFO_GNUPLOT_NOTFOUND
+ $HAS_GNUPLOT = 0;
+}
+
+#
+# write gnuplot scripts
+#
+plot_cycle_quality_heatmap( $CYC_QUAL_1, 1 );
+plot_cycle_quality_heatmap( $CYC_QUAL_2, 2 ) if $PAIRED;
+
+plot_cycle_quality_box( $CYC_QUAL_1_BOX, 1 );
+plot_cycle_quality_box( $CYC_QUAL_2_BOX, 2 ) if $PAIRED;
+
+plot_reads_quality($READS_QUAL);
+
+plot_lane_tile_quality( $LANE_TILE_QUAL_1, 1 );
+plot_lane_tile_quality( $LANE_TILE_QUAL_2, 2 ) if $PAIRED;
+
+plot_cycle_composition( $CYC_COMP_1, 1 );
+plot_cycle_composition( $CYC_COMP_2, 2 ) if $PAIRED;
+
+plot_reads_length($UMASK_LEN);
+
+plot_quality_qq($QUAL_QQ) if $PAIRED;
+
+#
+# subs
+#
+
+# gnuplot scripts
+sub plot_cycle_quality_heatmap {
+ my $base = shift;
+ my $side = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+ my $file_dat = catfile $dir_data, $base . '.dat';
+
+ # read table
+ # write data file for gnuplot
+ open my $h_tab, '<', $file_tab
+ or die "failed to open '$file_tab' for read: $!";
+ open my $h_dat, '>', $file_dat
+ or die "failed to open '$file_dat' for write: $!";
+
+ my @qual_list;
+
+ my $line = 0;
+ while (<$h_tab>) {
+ chomp;
+ if ( $line == 0 ) {
+ ( undef, @qual_list ) = split /\t/;
+ }
+ else {
+ my ( $cyc, @values ) = split /\t/;
+ for ( my $i = 0 ; $i < @values ; $i++ ) {
+ print $h_dat join( "\t", $cyc, $qual_list[$i], $values[$i] ),
+ "\n";
+ }
+ }
+ }
+ continue { $line++ }
+
+ close $h_tab;
+ close $h_dat;
+
+ # write script
+ my $x_min = -0.5;
+ my $x_max = $LENGTH + 0.5;
+ my $y_min = $QUAL_FROM - 0.5;
+ my $y_max = $QUAL_TO + 0.5;
+
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<HEREDOC;
+set title "Cycle Quality of Reads $side" font "*,$SZ_TITLE"
+unset key
+set terminal $FORMAT size $WIDTH,$HEIGHT
+set output "$file_chart"
+set palette rgbformulae 21,22,23
+
+set cblabel "Num reads" font "*,$SZ_TEXT"
+set cbtics font "*,$SZ_TEXT"
+
+set xrange [$x_min:$x_max]
+set yrange [$y_min:$y_max]
+set xlabel "Cycle" font "*,$SZ_TEXT"
+set ylabel "Quality" font "*,$SZ_TEXT"
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+plot '$file_dat' using 1:2:3 with image
+
+HEREDOC
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_cycle_quality_box {
+ my $base = shift;
+ my $side = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+
+ # write script
+ my $x_min = -0.5;
+ my $x_max = $LENGTH + 0.5;
+ my $y_min = $QUAL_FROM - 0.5;
+ my $y_max = $QUAL_TO + 0.5;
+
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<HEREDOC;
+set title "Cycle Quality of Reads $side" font "*,$SZ_TITLE"
+unset key
+set terminal $FORMAT size $WIDTH,$HEIGHT
+set output "$file_chart"
+
+set xrange [$x_min:$x_max]
+set yrange [$y_min:$y_max]
+set xlabel "Cycle" font "*,$SZ_TEXT"
+set ylabel "Quality" font "*,$SZ_TEXT"
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set boxwidth 0.8 relative
+
+plot '$file_tab' using 1:3:2:6:5 with candlesticks lc rgbcolor '#00007f',\\
+ '$file_tab' using 1:7 with lines lc rgbcolor 'red'
+
+HEREDOC
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_reads_quality {
+ my $base = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+
+ # write script
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<HEREDOC;
+set title "Reads Quality" font "*,$SZ_TITLE"
+set terminal $FORMAT size $WIDTH,$HEIGHT
+
+set key font "*,$SZ_TEXT"
+
+set xlabel "Quality" font "*,$SZ_TEXT"
+set ylabel "Num reads" font "*,$SZ_TEXT"
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set output "$file_chart"
+
+HEREDOC
+
+ print $h_plot
+"plot '$file_tab' using 1:2 lc rgbcolor '#ff0000' title 'read 1 quality' with lines,\\\n";
+ print $h_plot
+" '$file_tab' using 1:3 lc rgbcolor '#7f0000' title 'read 1 quality accum' with lines";
+
+ if ($PAIRED) {
+ print $h_plot ",\\\n";
+ print $h_plot
+" '$file_tab' using 1:4 lc rgbcolor '#0000ff' title 'read 2 quality' with lines,\\\n";
+ print $h_plot
+" '$file_tab' using 1:5 lc rgbcolor '#00007f' title 'read 2 quality accum' with lines\n";
+ }
+ else {
+ print $h_plot "\n";
+ }
+
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_lane_tile_quality {
+ my $base = shift;
+ my $side = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+ my $file_dat = catfile $dir_data, $base . '.dat';
+
+ # read ticks
+ # create dat file
+ my @titles;
+ my @ticks_list;
+
+ open my $h_tab, '<', $file_tab
+ or die "failed to open '$file_tab' for read: $!";
+ open my $h_dat, '>', $file_dat
+ or die "failed to open '$file_dat' for write: $!";
+ my $n = 0;
+ while (<$h_tab>) {
+ chomp;
+ if ( $n == 0 ) {
+ ( undef, @titles ) = split /\t/;
+ }
+ else {
+ my ( $lane, $tile, @data ) = split /\t/;
+ push @ticks_list, "\"lane $lane tile $tile\" $n";
+ print $h_dat join( "\t", $n, @data ), "\n";
+ }
+ }
+ continue { $n++ }
+ close $h_tab;
+ close $h_dat;
+
+ my $ticks_str = join ', ', @ticks_list;
+
+ # write script
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<HEREDOC;
+set title "Lane-Tile Quality for Reads $side" font "*,$SZ_TITLE"
+set terminal $FORMAT size $WIDTH,$HEIGHT
+
+set key outside font "*,$SZ_TEXT"
+
+set xlabel "Tiles" font "*,$SZ_TEXT"
+set ylabel "Num reads" font "*,$SZ_TEXT"
+set xtics rotate 90 ($ticks_str) font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set style fill solid
+set output "$file_chart"
+plot '$file_dat' using 1:(\$5+\$4+\$3+\$2):(1) with boxes lc rgbcolor "blue" title "quality > 30", \\
+ '$file_dat' using 1:(\$4+\$3+\$2):(1) with boxes lc rgbcolor "green" title "20 < quality < 30", \\
+ '$file_dat' using 1:(\$3+\$2):(1) with boxes lc rgbcolor "red" title "10 < quality < 20", \\
+ '$file_dat' using 1:2:(1) with boxes lc rgbcolor "black" title "quality < 10"
+HEREDOC
+
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_cycle_composition {
+ my $base = shift;
+ my $side = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+
+ my $x_min = -0.5;
+ my $x_max = $LENGTH + 0.5;
+
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<heredoc;
+set title "Cycle Composition for Read $side" font "*,$SZ_TITLE"
+set terminal $FORMAT size $WIDTH,$HEIGHT
+set style fill solid
+
+set key outside font "*,$SZ_TEXT"
+
+set xrange [$x_min:$x_max]
+set xlabel "Cycle" font "*,$SZ_TEXT"
+set ylabel "Num reads" font "*,$SZ_TEXT"
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set output "$file_chart"
+heredoc
+ print $h_plot "plot";
+
+ if ($MASK) {
+ print $h_plot <<heredoc;
+'$file_tab' using 1:(\$7+\$6+\$5+\$4+\$3+\$2) with boxes lc rgbcolor "yellow" title "MASK", \\
+heredoc
+ }
+
+ print $h_plot <<heredoc;
+'$file_tab' using 1:(\$6+\$5+\$4+\$3+\$2) with boxes lc rgbcolor "grey" title "N", \\
+ '$file_tab' using 1:(\$5+\$4+\$3+\$2) with boxes lc rgbcolor "black" title "C", \\
+ '$file_tab' using 1:(\$4+\$3+\$2) with boxes lc rgbcolor "blue" title "G", \\
+ '$file_tab' using 1:(\$3+\$2) with boxes lc rgbcolor "red" title "T", \\
+ '$file_tab' using 1:2 with boxes lc rgbcolor "green" title "A"
+heredoc
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_reads_length {
+ my $base = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<heredoc;
+set title "Reads Length" font "*,$SZ_TITLE"
+set terminal $FORMAT size $WIDTH,$HEIGHT
+
+set key font "*,$SZ_TEXT"
+
+set xlabel "Length" font "*,$SZ_TEXT"
+set ylabel "Num reads" font "*,$SZ_TEXT"
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set output "$file_chart"
+heredoc
+ print $h_plot
+"plot '$file_tab' using 1:2 lc rgbcolor '#ff0000' title 'read 1 length' with lines,\\\n";
+ print $h_plot
+" '$file_tab' using 1:3 lc rgbcolor '#7f0000' title 'read 1 length accum' with lines";
+ if ($PAIRED) {
+ print $h_plot ",\\\n";
+ print $h_plot
+" '$file_tab' using 1:4 lc rgbcolor '#0000ff' title 'read 2 length' with lines,\\\n";
+ print $h_plot
+" '$file_tab' using 1:5 lc rgbcolor '#00007f' title 'read 2 length accum' with lines\n";
+ }
+ else {
+ print $h_plot "\n";
+ }
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+sub plot_quality_qq {
+ my $base = shift;
+
+ my $file_tab = catfile $dir_data, $base . '.tab';
+ my $file_plot = catfile $dir_data, $base . '.gnuplot';
+ my $file_chart = catfile $dir_data, $base . '.' . $FORMAT;
+
+ my $label_x = $QUAL_FROM + 3;
+ my $label_y = $QUAL_TO - 3;
+
+ # get pearson r value
+ open my $h_tab, '<', $file_tab
+ or die "failed to open '$file_tab' for read: $!";
+ my $tab_header = <$h_tab>;
+ chomp $tab_header;
+ $tab_header =~ /# pearson correlation: (\S+)/
+ or die "failed to parse pearson correlation from '$tab_header'";
+ my $pearson_text = $1;
+ close $h_tab;
+
+ # write gnuplot script
+ open my $h_plot, '>', $file_plot or die $!;
+ print $h_plot <<heredoc;
+set title "Read Pair Quality QQ plot" font "*,$SZ_TITLE"
+set terminal $FORMAT size $WIDTH,$HEIGHT
+set output "$file_chart"
+unset key
+
+set xrange [$QUAL_FROM:$QUAL_TO]
+set yrange [$QUAL_FROM:$QUAL_TO]
+set xtics font "*,$SZ_TEXT"
+set ytics font "*,$SZ_TEXT"
+
+set label 'r = $pearson_text' at $label_x,$label_y font "*,$SZ_TEXT"
+plot '$file_tab' with lines
+
+heredoc
+ close $h_plot;
+
+ # run gnuplot
+ if ($HAS_GNUPLOT) {
+ system( 'gnuplot', $file_plot ) == 0 or die "gnuplot failed";
+ }
+}
+
+# help document
+sub show_help {
+ print <<heredoc;
+$0 - render ht_stat outputs
+
+Usage:
+ ht_stat_draw.pl --dir STAT_DIR
+
+Options:
+--dir the output directory of ht_stat.
+--format picture format. [$FORMAT]
+--width picture width. [$WIDTH]
+--height picture height. [$HEIGHT]
+--title-size font size for picture titles. [$SZ_TITLE]
+--text-size font size for axis ticks, legends, etc.. [$SZ_TEXT]
+--help show help
+heredoc
+ exit(0);
+}
diff --git a/src/ht2-stat.cpp b/src/ht2-stat.cpp
new file mode 100644
index 0000000..5db8e12
--- /dev/null
+++ b/src/ht2-stat.cpp
@@ -0,0 +1,759 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <map>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+#include <algorithm>
+#include <cmath>
+#include <queue>
+
+#include <cstdio>
+
+#include "htio2/Cast.h"
+#include "htio2/FastqIO.h"
+#include "htio2/QualityUtil.h"
+#include "htio2/HeaderUtil.h"
+
+#define USE_se_pe
+#define USE_encode
+#define USE_header_format
+#define USE_mask
+
+#include "htio2/RingBuffer.h"
+#include "htqc/Options.h"
+#include "htqc/BaseQualCounter.h"
+#include "htqc/FastqStat.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+// We don't care strand in this program, so simply let them identical.
+#define PE_STRAND_FILE htio2::STRAND_FWD, htio2::STRAND_FWD
+#define PE_STRAND_OBJ htio2::STRAND_FWD, htio2::STRAND_FWD
+
+using namespace std;
+using namespace htqc;
+using namespace htio2::juce;
+
+//
+// thread devices
+//
+struct StatWorker;
+vector<StatWorker*> WORKERS;
+
+queue<ssize_t> IDX_FREE;
+queue<ssize_t> IDX_FILLED;
+
+// list of reads, one for each thread
+vector<htio2::FastqSeq> READ_BUFFER_1;
+vector<htio2::FastqSeq> READ_BUFFER_2;
+
+size_t N_PROCESSED = 0;
+
+//
+// command-line arguments
+//
+int OPT_num_threads = 2;
+htio2::Option OPT_num_threads_ENTRY("threads", 't', OPTION_GROUP_MISC,
+ &OPT_num_threads, htio2::Option::FLAG_NONE,
+ "Number of worker threads.", "INT");
+
+string OPT_dir_out;
+htio2::Option OPT_dir_out_ENTRY("out", 'o', OPTION_GROUP_IO,
+ &OPT_dir_out, htio2::Option::FLAG_NONE,
+ "Output directory.", "DIR");
+
+//
+// thread body
+//
+
+struct StatWorker: public Thread
+{
+
+ StatWorker(int thread_id)
+ : Thread(String(thread_id))
+ , todo(OPT_num_threads * 2)
+ , done(OPT_num_threads * 2)
+ , stat_a(OPT_mask, OPT_encode, OPT_header_format, OPT_header_sra)
+ , stat_b(OPT_mask, OPT_encode, OPT_header_format, OPT_header_sra)
+ {
+ }
+
+ virtual void run()
+ {
+ while (1)
+ {
+ ssize_t i = numeric_limits<ssize_t>::min();
+
+ // get indices of the todo read
+ todo.pop_sync(i);
+
+ // exit when get the signal
+ if (i == -1) return;
+
+
+ // process fetched ones
+ if (OPT_se)
+ {
+ stat_a.record_seq(READ_BUFFER_1[i]);
+ }
+ else
+ {
+ stat_a.record_seq(READ_BUFFER_1[i]);
+ stat_b.record_seq(READ_BUFFER_2[i]);
+ }
+
+ // push back processed read slot
+ done.push_sync(i);
+ }
+ }
+
+ htio2::RingBuffer<ssize_t> todo;
+ htio2::RingBuffer<ssize_t> done;
+ FastqStat stat_a;
+ FastqStat stat_b;
+};
+
+//
+// functions
+//
+
+void write_cycle_quality_table(const File& file, const FastqStat& stat)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "#cycle";
+ for (int q = stat.qual_from; q <= stat.qual_to; q++)
+ OUT << "\t" << q;
+ OUT << endl;
+
+ // write qualities for each cycle
+ for (int i = 0; i < stat.observed_max_len; i++)
+ {
+ const BaseQualCounter& quals = stat.base_qual_counter[i];
+ OUT << i + 1;
+ for (int q = stat.qual_from; q <= stat.qual_to; q++)
+ OUT << "\t" << quals.get_num(q);
+ OUT << endl;
+ }
+}
+
+void write_cycle_composition(const File& file, const FastqStat& stat, bool qual_mask)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "cycle" << "\t" << "A" << "\t" << "T" << "\t" << "G" << "\t" << "C" << "\t" << "N";
+ if (qual_mask) OUT << "\t" << "mask";
+ OUT << endl;
+
+ // write composition for each cycle
+ for (int i = 0; i < stat.observed_max_len; i++)
+ {
+ const BaseCounter& counter = stat.base_compo_counter[i];
+ OUT << i + 1 << "\t"
+ << counter.a << "\t"
+ << counter.t << "\t"
+ << counter.g << "\t"
+ << counter.c << "\t"
+ << counter.n << "\t";
+ if (qual_mask) OUT << counter.mask;
+ OUT << endl;
+ }
+}
+
+void write_se_seq_quality(const File& file, const FastqStat& stat)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "#quality\tread 1 num\tread 1 accumulate" << endl;
+
+ int q = stat.qual_from;
+ int val_a = 0;
+ int sum_a = 0;
+
+ while (1)
+ {
+ if (q > stat.qual_to) break;
+
+ val_a = stat.read_qual_counter.get_num(q);
+ sum_a += val_a;
+ OUT << q << "\t" << val_a << "\t" << sum_a << endl;
+
+ q++;
+ }
+
+}
+
+void write_pe_seq_quality(const File& file, const FastqStat& stat_a, const FastqStat& stat_b)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "#quality\tread 1 num\tread 1 accumulate\tread 2 num\tread 2 accumulate" << endl;
+
+ int q = stat_a.qual_from;
+ int val_a = 0;
+ int sum_a = 0;
+ int val_b = 0;
+ int sum_b = 0;
+
+ while (1)
+ {
+ if (q > stat_a.qual_to) break;
+
+ val_a = stat_a.read_qual_counter.get_num(q);
+ val_b = stat_b.read_qual_counter.get_num(q);
+ sum_a += val_a;
+ sum_b += val_b;
+
+ OUT << q << "\t" << val_a << "\t" << sum_a << "\t" << val_b << "\t" << sum_b << endl;
+
+ q++;
+ }
+}
+
+void write_se_seq_length(const File& file, const FastqStat& stat)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "#length" << "\t" << "read 1 num" << "\t" << "read 1 accumulate" << endl;
+
+ {
+ int i = 1;
+ int val_a = 0;
+ int sum_a = 0;
+
+ while (1)
+ {
+ if (i > stat.observed_max_len) break;
+
+ val_a = stat.read_len_counter[i];
+ sum_a += val_a;
+ OUT << i << "\t" << val_a << "\t" << sum_a << endl;
+
+ i++;
+ }
+ }
+}
+
+void write_pe_seq_length(const File& file, const FastqStat& stat_a, const FastqStat& stat_b)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ if (stat_a.observed_max_len != stat_b.observed_max_len)
+ {
+ cerr << "ERROR: store has inequal length: " << stat_a.observed_max_len << " and " << stat_b.observed_max_len << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ size_t length = stat_a.observed_max_len;
+
+ OUT << "#length" << "\t" << "read 1 num" << "\t" << "read 1 accumulate" << "\t" << "read 2 num" << "\t" << "read 2 accumulate" << endl;
+
+ {
+ int i = 1;
+ int val_a = 0;
+ int sum_a = 0;
+ int val_b = 0;
+ int sum_b = 0;
+
+ while (1)
+ {
+ if (i > length) break;
+
+ val_a = stat_a.read_len_counter[i];
+ val_b = stat_b.read_len_counter[i];
+ sum_a += val_a;
+ sum_b += val_b;
+
+ OUT << i << "\t" << val_a << "\t" << sum_a << "\t" << val_b << "\t" << sum_b << endl;
+
+ i++;
+ }
+ }
+}
+
+void write_lane_tile_quality(const File& file, const FastqStat& stat)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // write header
+ OUT << "#lane\ttile\tqual<10\t10<qual<20\t20<qual<30\tqual>30" << endl;
+
+ // write content
+ for (
+ map< int, map<int, TileQualCounter> >::const_iterator it_lane = stat.tile_read_qual_counter.begin();
+ it_lane != stat.tile_read_qual_counter.end();
+ it_lane++
+ )
+ {
+ const map<int, TileQualCounter>* lane_quals = &(it_lane->second);
+
+ for (
+ map<int, TileQualCounter>::const_iterator it_tile = lane_quals->begin();
+ it_tile != lane_quals->end();
+ it_tile++
+ )
+ {
+ const TileQualCounter* tile_quals = &(it_tile->second);
+ OUT << it_lane->first << "\t"
+ << it_tile->first << "\t"
+ << tile_quals->num_reads_10 << "\t"
+ << tile_quals->num_reads_10_20 << "\t"
+ << tile_quals->num_reads_20_30 << "\t"
+ << tile_quals->num_reads_30 << endl;
+ }
+ }
+}
+
+void write_qq(const File& file, const FastqStat& stat_a, const FastqStat& stat_b)
+{
+ ofstream OUT(file.getFullPathName().toRawUTF8());
+
+ // calculate pearson correlation
+ const size_t n = stat_a.read_quals.size();
+
+ double sum_xy(0);
+ double sum_x(0);
+ double sum_y(0);
+ double sum_xx(0);
+ double sum_yy(0);
+
+ for (size_t i = 0; i < n; i++)
+ {
+ float x = stat_a.read_quals[i];
+ float y = stat_b.read_quals[i];
+ sum_xy += x*y;
+ sum_x += x;
+ sum_y += y;
+ sum_xx += x*x;
+ sum_yy += y*y;
+ }
+
+ double pearson =
+ (
+ n * sum_xy - sum_x * sum_y
+ ) / (
+ sqrt(n * sum_xx - sum_x * sum_x) * sqrt(n * sum_yy - sum_y * sum_y)
+ );
+
+ vector<float> quals_a_sorted = stat_a.read_quals;
+ vector<float> quals_b_sorted = stat_b.read_quals;
+
+ sort(quals_a_sorted.begin(), quals_a_sorted.end());
+ sort(quals_b_sorted.begin(), quals_b_sorted.end());
+ int num_seq = stat_a.read_quals.size();
+ int step = (num_seq < 200 ? 1 : num_seq / 200);
+
+ OUT << "# pearson correlation: " << pearson << endl;
+
+ // write data
+ for (int i = 0; i < num_seq; i += step)
+ {
+ OUT << quals_a_sorted[i] << "\t" << quals_b_sorted[i] << endl;
+ }
+}
+
+//
+// main
+//
+
+void parse_options(int argc, char** argv)
+{
+ htio2::OptionParser opt_psr;
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_dir_out_ENTRY);
+
+ opt_psr.add_option(OPT_se_ENTRY);
+ opt_psr.add_option(OPT_pe_ENTRY);
+ opt_psr.add_option(OPT_pe_itlv_ENTRY);
+ opt_psr.add_option(OPT_pe_strand_ENTRY);
+ opt_psr.add_option(OPT_encode_ENTRY);
+ opt_psr.add_option(OPT_mask_ENTRY);
+ opt_psr.add_option(OPT_header_format_ENTRY);
+ opt_psr.add_option(OPT_header_sra_ENTRY);
+
+ opt_psr.add_option(OPT_num_threads_ENTRY);
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ //
+ // show help
+ //
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - summarize sequencing reads quality"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_se_pe();
+
+ ensure_encode();
+ ensure_header_format();
+
+ if ((OPT_encode == htio2::ENCODE_SOLEXA) && OPT_mask)
+ {
+ cerr << "ERROR: solexa mode cannot be used together with mask" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_options()
+{
+ show_se_pe();
+ show_files_in();
+ cout << "# output directory: " << OPT_dir_out << endl;
+ show_encode();
+ show_header_format();
+ show_mask();
+}
+
+void send_all_filled_slots()
+{
+ while (IDX_FILLED.size())
+ {
+ // get a filled slot
+ ssize_t slot_i = IDX_FILLED.front();
+ IDX_FILLED.pop();
+
+ // send this slot to a worker
+ bool slot_sent = false;
+ while (!slot_sent)
+ {
+ for (int i_worker = 0; i_worker < OPT_num_threads; i_worker++)
+ {
+ slot_sent = WORKERS[i_worker]->todo.push(slot_i);
+ if (slot_sent) break;
+ }
+ }
+
+ // log
+ N_PROCESSED++;
+ if (!OPT_quiet && (N_PROCESSED % LOG_BLOCK == 0))
+ cout << "\t" << N_PROCESSED << " reads done" << endl;
+ }
+}
+
+void fetch_empty_slots()
+{
+ for (int i_worker = 0; i_worker < OPT_num_threads; i_worker++)
+ {
+ ssize_t slot_i;
+ if (WORKERS[i_worker]->done.pop(slot_i))
+ {
+ IDX_FREE.push(slot_i);
+ }
+ if (WORKERS[i_worker]->done.pop(slot_i))
+ {
+ IDX_FREE.push(slot_i);
+ }
+ }
+}
+
+void do_single()
+{
+ htio2::FastqSeq curr;
+
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ bool fh_re = false;
+
+ for (;;)
+ {
+ while (IDX_FREE.size())
+ {
+ ssize_t slot_i = IDX_FREE.front();
+ IDX_FREE.pop();
+
+ fh_re = fh_in.next_seq(READ_BUFFER_1[slot_i]);
+ if (!fh_re)
+ break;
+
+ IDX_FILLED.push(slot_i);
+ }
+
+ // send all filled slots to worker
+ send_all_filled_slots();
+
+ // return if finished
+ if (!fh_re)
+ break;
+
+ // try to fetch some empty slots
+ fetch_empty_slots();
+ }
+
+ if (!OPT_quiet)
+ cout << "\t" << N_PROCESSED << " done" << endl;
+}
+
+
+void do_paired()
+{
+ htqc::MultiSeqFilePE::Ptr fh_in;
+
+ if (OPT_pe_itlv)
+ {
+ fh_in = new htqc::MultiSeqFilePE(OPT_files_in,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+ else
+ {
+ vector<string> files_in_a;
+ vector<string> files_in_b;
+ separate_paired_files(OPT_files_in, files_in_a, files_in_b);
+
+ fh_in = new htqc::MultiSeqFilePE(files_in_a,
+ files_in_b,
+ PE_STRAND_FILE,
+ OPT_compress);
+ }
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ bool fh_re = false;
+
+ for (;;)
+ {
+ // read from file
+ while (IDX_FREE.size())
+ {
+ ssize_t slot_i = IDX_FREE.front();
+ IDX_FREE.pop();
+
+ fh_re = fh_in->next_pair(READ_BUFFER_1[slot_i], READ_BUFFER_2[slot_i], PE_STRAND_OBJ);
+ if (!fh_re)
+ break;
+
+ IDX_FILLED.push(slot_i);
+ }
+
+ // send all filled slots to worker
+ send_all_filled_slots();
+
+ // return if finished
+ if (!fh_re)
+ break;
+
+ // try to read empty slots
+ fetch_empty_slots();
+ }
+
+ if (!OPT_quiet)
+ cout << "\t" << N_PROCESSED << " pairs done" << endl;
+}
+
+void execute()
+{
+ // create output directory
+ File dir_out(OPT_dir_out);
+ if (!dir_out.isDirectory())
+ {
+ Result re = dir_out.createDirectory();
+ if (re.failed())
+ {
+ fprintf(stderr, "ERROR: failed to create output directory \"%s\": %s\n",
+ OPT_dir_out.c_str(), re.getErrorMessage().toRawUTF8());
+ }
+ }
+
+ //
+ // create thread communication utilities
+ //
+ READ_BUFFER_1.resize(OPT_num_threads*2);
+ READ_BUFFER_2.resize(OPT_num_threads*2);
+
+ // mark all slots as ready to use
+ for (ssize_t i = 0; i < OPT_num_threads*2; i++)
+ {
+ IDX_FREE.push(i);
+ }
+
+ // create threads
+ for (int i = 0; i < OPT_num_threads; i++)
+ {
+ WORKERS.push_back(new StatWorker(i));
+ WORKERS.back()->startThread();
+ }
+
+ //
+ // traverse input
+ //
+ if (OPT_se)
+ do_single();
+ else if (OPT_pe)
+ do_paired();
+ else
+ throw runtime_error("neither single-end nor paired-end");
+
+ // send stop signal
+ for (int i = 0; i < OPT_num_threads; i++)
+ {
+ WORKERS[i]->todo.push_sync(-1);
+ }
+
+ // join threads
+ // reduce statistic results from all threads into one
+ FastqStat stat_a(OPT_mask, OPT_encode, OPT_header_format, OPT_header_sra);
+ FastqStat stat_b(OPT_mask, OPT_encode, OPT_header_format, OPT_header_sra);
+
+ if (!OPT_quiet) cout << "join threads" << endl;
+ for (int i = 0; i < OPT_num_threads; i++)
+ {
+ StatWorker* worker = WORKERS[i];
+ if (!OPT_quiet) cout << " thread " << i << endl;
+ worker->waitForThreadToExit(-1);
+
+ if (worker->stat_a.observed_max_len < stat_a.observed_max_len)
+ worker->stat_a.try_expand_store(stat_a.observed_max_len);
+ stat_a += worker->stat_a;
+
+ if (!OPT_se)
+ {
+ if (worker->stat_b.observed_max_len < stat_b.observed_max_len)
+ worker->stat_b.try_expand_store(stat_b.observed_max_len);
+ stat_b += worker->stat_b;
+ }
+
+ delete WORKERS[i];
+ }
+
+ if (!OPT_se)
+ {
+ if (stat_a.observed_max_len > stat_b.observed_max_len)
+ stat_b.try_expand_store(stat_a.observed_max_len);
+ else
+ stat_a.try_expand_store(stat_b.observed_max_len);
+ }
+
+ //
+ // write result
+ //
+ if (!OPT_quiet) cout << "write result" << endl;
+
+ // reads info
+ File file_info = dir_out.getChildFile("info.tab");
+ ofstream INFO(file_info.getFullPathName().toRawUTF8());
+ INFO << "amount" << "\t" << N_PROCESSED << (OPT_se ? "" : "x2") << endl
+ << "encode" << "\t" << htio2::to_string(OPT_encode) << endl
+ << "paired" << "\t" << bool_to_string(OPT_pe) << endl
+ << "length" << "\t" << stat_a.observed_max_len << endl
+ << "mask" << "\t" << bool_to_string(OPT_mask) << endl
+ << "quality range" << "\t" << stat_a.qual_from << '-' << stat_a.qual_to << endl;
+
+ // cycle quality
+ File file_cycle_qual_1 = dir_out.getChildFile("cycle_quality_1.tab");
+ if (!OPT_quiet)
+ cout << " " << file_cycle_qual_1.getFullPathName().toStdString() << endl;
+
+ write_cycle_quality_table(file_cycle_qual_1, stat_a);
+
+ if (!OPT_se)
+ {
+ File file_cyc_qual_2 = dir_out.getChildFile("cycle_quality_2.tab");
+ if (!OPT_quiet)
+ cout << " " << file_cyc_qual_2.getFullPathName().toStdString() << endl;
+
+ write_cycle_quality_table(file_cyc_qual_2, stat_b);
+ }
+
+ // read quality
+ File file_read_qual = dir_out.getChildFile("reads_quality.tab");
+ if (!OPT_quiet) cout << " " << file_read_qual.getFullPathName().toStdString() << endl;
+
+ if (!OPT_se)
+ {
+ write_pe_seq_quality(file_read_qual, stat_a, stat_b);
+ }
+ else
+ {
+ write_se_seq_quality(file_read_qual, stat_a);
+ }
+
+ // lane and tile quality
+ File file_lane_tile_qual_1 = dir_out.getChildFile("lane_tile_quality_1.tab");
+ if (!OPT_quiet)
+ cout << " " << file_lane_tile_qual_1.getFullPathName().toStdString() << endl;
+ write_lane_tile_quality(file_lane_tile_qual_1, stat_a);
+
+ if (!OPT_se)
+ {
+ File file_lane_tile_qual_2 = dir_out.getChildFile("lane_tile_quality_2.tab");
+ if (!OPT_quiet)
+ cout << " " << file_lane_tile_qual_2.getFullPathName().toStdString() << endl;
+ write_lane_tile_quality(file_lane_tile_qual_2, stat_b);
+ }
+
+ // cycle composition
+ File file_cycle_comp_1 = dir_out.getChildFile("cycle_composition_1.tab");
+ if (!OPT_quiet)
+ cout << " " << file_cycle_comp_1.getFullPathName().toStdString() << endl;
+ write_cycle_composition(file_cycle_comp_1, stat_a, OPT_mask);
+
+ if (!OPT_se)
+ {
+ File file_cycle_comp_2 = dir_out.getChildFile("cycle_composition_2.tab");
+ if (!OPT_quiet) cout << " " << file_cycle_comp_2.getFullPathName().toStdString() << endl;
+ write_cycle_composition(file_cycle_comp_2, stat_b, OPT_mask);
+ }
+
+ // read length
+ File file_read_length = dir_out.getChildFile("reads_length.tab");
+ if (!OPT_quiet) cout << " " << file_read_length.getFullPathName().toStdString() << endl;
+
+ if (!OPT_se)
+ {
+ write_pe_seq_length(file_read_length, stat_a, stat_b);
+ }
+ else
+ {
+ write_se_seq_length(file_read_length, stat_a);
+ }
+
+ // QQ plot
+ if (!OPT_se)
+ {
+ File file_qual_qq = dir_out.getChildFile("quality_QQ.tab");
+ if (!OPT_quiet) cout << " " << file_qual_qq.getFullPathName().toStdString() << endl;
+ write_qq(file_qual_qq, stat_a, stat_b);
+ }
+
+ if (!OPT_quiet)
+ printf("all table written\n");
+}
+
diff --git a/src/ht2-trim.cpp b/src/ht2-trim.cpp
new file mode 100644
index 0000000..e3a15dc
--- /dev/null
+++ b/src/ht2-trim.cpp
@@ -0,0 +1,280 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/QualityUtil.h"
+
+#define USE_prefix_out
+#define USE_encode
+#define USE_se_pe
+#include "htqc/Options.h"
+#include "htqc/App.h"
+#include "htqc/MultiSeqFile.h"
+
+using namespace std;
+using namespace htqc;
+
+//
+// type definitions
+//
+
+enum TrimSide
+{
+ TRIM_FROM_HEAD = 1,
+ TRIM_FROM_TAIL = 1 << 1
+};
+
+string trim_side_to_string(TrimSide side)
+{
+ if (side == TRIM_FROM_HEAD)
+ return "head";
+ else if (side == TRIM_FROM_TAIL)
+ return "tail";
+ else if (side == (TRIM_FROM_HEAD | TRIM_FROM_TAIL))
+ return "both";
+ else
+ {
+ cerr << "ERROR: invalid side enum value: " << int(side) << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+//
+// command line options
+//
+#define DEFAULT_KMER_SIZE 5
+#define DEFAULT_QUAL_CUT 20
+
+#define OPTION_GROUP_TRIM "Trimming Options"
+
+unsigned char OPT_trim_side = TRIM_FROM_HEAD | TRIM_FROM_TAIL;
+string OPT_trim_side_STR("both");
+htio2::Option OPT_trim_side_ENTRY("side", 'S', OPTION_GROUP_TRIM,
+ &OPT_trim_side_STR, htio2::Option::FLAG_NONE,
+ "Trim is performed on which side.", "head|tail|both");
+
+size_t OPT_word_size = DEFAULT_KMER_SIZE;
+htio2::Option OPT_word_size_ENTRY("word-size", 'W', OPTION_GROUP_TRIM,
+ &OPT_word_size, htio2::Option::FLAG_NONE,
+ "Number of continuous high quality bases.", "INT");
+
+int OPT_qual_cut = DEFAULT_QUAL_CUT;
+htio2::Option OPT_qual_cut_ENTRY("quality", 'Q', OPTION_GROUP_TRIM,
+ &OPT_qual_cut, htio2::Option::FLAG_NONE,
+ "Quality cutoff.", "INT");
+
+//
+// subs
+//
+
+void parse_options(int argc, char** argv)
+{
+ // we are always processing single-end
+ OPT_se = true;
+
+ htio2::OptionParser opt_psr;
+
+ opt_psr.add_option(OPT_files_in_ENTRY);
+ opt_psr.add_option(OPT_prefix_out_ENTRY);
+
+ opt_psr.add_option(OPT_trim_side_ENTRY);
+ opt_psr.add_option(OPT_qual_cut_ENTRY);
+ opt_psr.add_option(OPT_word_size_ENTRY);
+
+ opt_psr.add_option(OPT_encode_ENTRY);
+ opt_psr.add_option(OPT_mask_ENTRY);
+
+ opt_psr.add_option(OPT_quiet_ENTRY);
+ opt_psr.add_option(OPT_help_ENTRY);
+ opt_psr.add_option(OPT_version_ENTRY);
+
+ opt_psr.parse_options(argc, argv);
+
+ //
+ // show help
+ //
+ if (OPT_help)
+ {
+ cout << endl
+ << argv[0] << " - remove bad bases from reads head or tail"
+ << endl << endl
+ << opt_psr.format_document();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (OPT_version) show_version_and_exit();
+}
+
+void validate_options()
+{
+ ensure_files_in();
+ ensure_prefix_out();
+
+ if (OPT_word_size < 1 || OPT_word_size > 16)
+ {
+ cerr << "ERROR: invalid kmer size: " << OPT_word_size << ", must between 1 - 16" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (OPT_trim_side_STR == "head")
+ OPT_trim_side = TRIM_FROM_HEAD;
+ else if (OPT_trim_side_STR == "tail")
+ OPT_trim_side = TRIM_FROM_TAIL;
+ else if (OPT_trim_side_STR == "both")
+ OPT_trim_side = TRIM_FROM_HEAD | TRIM_FROM_TAIL;
+ else
+ {
+ cerr << "ERROR: invalid trim side: " << OPT_trim_side_STR << ", must be head|tail|both" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ ensure_encode();
+}
+
+void show_options()
+{
+ show_files_in();
+ show_prefix_out();
+ cout << "# trim side: " << OPT_trim_side_STR << endl;
+ cout << "# word size: " << OPT_word_size << endl;
+ cout << "# quality cutoff: " << OPT_qual_cut << endl;
+ cout << "# encode: " << to_string(OPT_encode) << endl;
+}
+
+string to_str(uint16_t kmer)
+{
+ string re;
+ for (size_t i = 0; i < OPT_word_size; i++)
+ {
+ if (kmer & (1 << i))
+ re.push_back('1');
+ else
+ re.push_back('0');
+ }
+ return re;
+}
+
+void execute()
+{
+ // output
+ string file_out;
+ add_fastq_suffix_se(OPT_prefix_out, OPT_compress, file_out);
+ check_output_overwrite(OPT_files_in, file_out);
+ htio2::SeqIO::Ptr fh_out(htio2::SeqIO::New(file_out, htio2::WRITE, OPT_compress));
+
+
+ // generate kmer that is perfect
+ uint16_t perfect = 0;
+ for (size_t i = 0; i < OPT_word_size; i++)
+ perfect |= 1 << i;
+
+ //
+ // traverse input
+ //
+ size_t n = 0;
+ htio2::FastqSeq curr_seq;
+ htio2::FastqSeq curr_seq_sub;
+
+ htqc::MultiSeqFileSE fh_in(OPT_files_in, OPT_compress);
+
+ while (fh_in.next_seq(curr_seq))
+ {
+ n++;
+
+ ssize_t len = curr_seq.length();
+ ssize_t i_start = 0;
+ ssize_t i_end = len - 1;
+
+ // sequence must be long enough
+ if (len < OPT_word_size * 2)
+ {
+ i_end = i_start - 1;
+ goto TRIM_DONE;
+ }
+
+ // trim from head
+ if (OPT_trim_side & TRIM_FROM_HEAD)
+ {
+ // the first kmer
+ uint16_t kmer = 0;
+ for (size_t i = 0; i < OPT_word_size; i++)
+ {
+ int32_t qual = htio2::decode_quality(curr_seq.quality[i], OPT_encode);
+ bool curr_ok = (OPT_qual_cut <= qual);
+ kmer |= curr_ok << i;
+ }
+
+ // traverse all remaining kmers
+ if (kmer != perfect)
+ {
+ while (true)
+ {
+ if (i_start == len - OPT_word_size) break;
+ i_start++;
+
+ int32_t qual = htio2::decode_quality(curr_seq.quality[i_start + OPT_word_size - 1], OPT_encode);
+ bool curr_ok = (OPT_qual_cut <= qual);
+ kmer >>= 1;
+ kmer |= curr_ok << (OPT_word_size - 1);
+ kmer &= perfect;
+ if (kmer == perfect) break;
+ }
+ }
+ }
+
+ // trim from tail
+ if (OPT_trim_side & TRIM_FROM_TAIL)
+ {
+ // the last kmer
+ uint16_t kmer = 0;
+ for (size_t i = 0; i < OPT_word_size; i++)
+ {
+ int32_t qual = htio2::decode_quality(curr_seq.quality[len - OPT_word_size + i], OPT_encode);
+ bool curr_ok = (OPT_qual_cut <= qual);
+ kmer |= curr_ok << i;
+ }
+
+ // traverse all remaining kmers
+ if (kmer != perfect)
+ {
+ while (true)
+ {
+ if (i_end == i_start - 1) break;
+ i_end--;
+ int qual = htio2::decode_quality(curr_seq.quality[i_end - OPT_word_size + 1], OPT_encode);
+ bool curr_ok = (OPT_qual_cut <= qual);
+ kmer <<= 1;
+ kmer |= curr_ok;
+ kmer &= perfect;
+ if (kmer == perfect) break;
+ }
+ }
+ }
+
+ // write output
+TRIM_DONE:
+ int trim_len = i_end - i_start + 1;
+ curr_seq.subseq(curr_seq_sub, i_start, trim_len);
+ fh_out->write_seq(curr_seq_sub);
+
+ if (!OPT_quiet && (n % LOG_BLOCK == 0))
+ cout << " " << n << " reads" << endl;
+ }
+
+
+ if (!OPT_quiet)
+ cout << " " << n << " reads" << endl;
+}
diff --git a/src/ht_config.h.in b/src/ht_config.h.in
new file mode 100644
index 0000000..dff234e
--- /dev/null
+++ b/src/ht_config.h.in
@@ -0,0 +1,8 @@
+#ifndef HT_CONFIG_H
+#define HT_CONFIG_H
+
+#define HTQC_VERSION_MAJOR @CPACK_PACKAGE_VERSION_MAJOR@
+#define HTQC_VERSION_MINOR @CPACK_PACKAGE_VERSION_MINOR@
+#define HTQC_VERSION_PATCH @CPACK_PACKAGE_VERSION_PATCH@
+
+#endif // HT_CONFIG_H
\ No newline at end of file
diff --git a/src/htio2/Cast.cpp b/src/htio2/Cast.cpp
new file mode 100644
index 0000000..07a5561
--- /dev/null
+++ b/src/htio2/Cast.cpp
@@ -0,0 +1,353 @@
+#include "htio2/Cast.h"
+#include "htio2/StringUtil.h"
+
+#include <stdlib.h>
+
+using namespace std;
+
+namespace htio2
+{
+
+string _prepare_input_(const std::string& input)
+{
+ size_t i_begin = input.find_first_not_of(" \t");
+ return to_lower_case(input.substr(i_begin));
+}
+
+template <>
+bool from_string<bool>(const std::string& input, bool& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "yes" || input_lc == "true" || input_lc == "y" || input_lc == "t" || input_lc == "1")
+ {
+ output = true;
+ return true;
+ }
+ else if (input_lc == "no" || input_lc == "false" || input_lc == "n" || input_lc == "f" || input_lc == "0")
+ {
+ output = false;
+ return true;
+ }
+ else
+ return false;
+}
+
+// cast to signed integers
+#define FROM_STRING_INT_IMPL(_out_type_, _func_) \
+ char* p_end = 0;\
+ _out_type_ tmp = _func_(input.c_str(), &p_end, 0);\
+ if (p_end != input.c_str())\
+ {\
+ output = tmp;\
+ return true;\
+ }\
+ else\
+ return false;\
+
+#define FROM_STRING_FLOAT_IMPL(_out_type_, _func_)\
+ char* p_end = 0;\
+ _out_type_ tmp = _func_(input.c_str(), &p_end);\
+ if (p_end != input.c_str())\
+ {\
+ output = tmp;\
+ return true;\
+ }\
+ else\
+ return false;\
+
+template <>
+bool from_string<short>(const std::string& input, short& output)
+{
+ FROM_STRING_INT_IMPL(short, strtol);
+}
+
+template <>
+bool from_string<int>(const std::string& input, int& output)
+{
+ FROM_STRING_INT_IMPL(int, strtol);
+}
+
+template <>
+bool from_string<long>(const std::string& input, long& output)
+{
+ FROM_STRING_INT_IMPL(long, strtol);
+}
+
+template <>
+bool from_string<long long>(const std::string& input, long long& output)
+{
+ FROM_STRING_INT_IMPL(long long, strtoll);
+}
+
+// cast to unsigned integers
+template <>
+bool from_string<unsigned short>(const std::string& input, unsigned short& output)
+{
+ FROM_STRING_INT_IMPL(unsigned short, strtoul);
+}
+
+template <>
+bool from_string<unsigned int>(const std::string& input, unsigned int& output)
+{
+ FROM_STRING_INT_IMPL(unsigned int, strtoul);
+}
+
+template <>
+bool from_string<unsigned long>(const std::string& input, unsigned long& output)
+{
+ FROM_STRING_INT_IMPL(unsigned long, strtoul);
+}
+
+template <>
+bool from_string<unsigned long long>(const std::string& input, unsigned long long& output)
+{
+ FROM_STRING_INT_IMPL(unsigned long long, strtoull);
+}
+
+// cast to floating points
+template <>
+bool from_string<float>(const std::string& input, float& output)
+{
+ FROM_STRING_FLOAT_IMPL(float, strtof);
+}
+
+template <>
+bool from_string<double>(const std::string& input, double& output)
+{
+ FROM_STRING_FLOAT_IMPL(double, strtod);
+}
+
+template <>
+bool from_string<long double>(const std::string& input, long double& output)
+{
+ FROM_STRING_FLOAT_IMPL(long double, strtold);
+}
+
+// cast to HTIO enum types
+template<>
+bool from_string<Strand>(const std::string& input, Strand& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "forward" || input_lc == "fwd" || input_lc == "1")
+ {
+ output = STRAND_FWD;
+ return true;
+ }
+ else if (input_lc == "reverse" || input_lc == "rev" || input_lc == "-1")
+ {
+ output = STRAND_REV;
+ return true;
+ }
+ else if (input_lc == "unknown" || input_lc == "0")
+ {
+ output = STRAND_UNKNOWN;
+ return true;
+ }
+ else
+ return false;
+}
+
+template<>
+bool from_string<SeqFormat>(const std::string& input, SeqFormat& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "fastq" || input_lc == "fq")
+ {
+ output = FORMAT_FASTQ;
+ return true;
+ }
+ else if (input_lc == "fasta" || input_lc == "fas" || input_lc == "fa" || input_lc == "fna")
+ {
+ output = FORMAT_FASTA;
+ return true;
+ }
+ else
+ return false;
+}
+
+template<>
+bool from_string<HeaderFormat>(const std::string& input, HeaderFormat& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "pri_casava1.8")
+ {
+ output = HEADER_PRI_1_8;
+ return true;
+ }
+ else if (input_lc == "casava1.8")
+ {
+ output = HEADER_1_8;
+ return true;
+ }
+ else if (input_lc == "unknown")
+ {
+ output = HEADER_UNKNOWN;
+ return true;
+ }
+ else
+ return false;
+}
+
+template<>
+bool from_string<QualityEncode>(const std::string& input, QualityEncode& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "sanger")
+ {
+ output = ENCODE_SANGER;
+ return true;
+ }
+ else if (input_lc == "solexa")
+ {
+ output = ENCODE_SOLEXA;
+ return true;
+ }
+ else if (input_lc == "illumina")
+ {
+ output = ENCODE_ILLUMINA;
+ return true;
+ }
+ else if (input_lc == "casava1.8")
+ {
+ output = ENCODE_CASAVA_1_8;
+ return true;
+ }
+ else if (input_lc == "unknown")
+ {
+ output = ENCODE_UNKNOWN;
+ return true;
+ }
+ else
+ return false;
+}
+
+template<>
+bool from_string<CompressFormat>(const std::string& input, CompressFormat& output)
+{
+ string input_lc = _prepare_input_(input);
+
+ if (input_lc == "plain")
+ {
+ output = COMPRESS_PLAIN;
+ return true;
+ }
+ else if (input_lc == "gzip" || input_lc == "gz")
+ {
+ output = COMPRESS_GZIP;
+ return true;
+ }
+ else if (input_lc == "lzma" || input_lc == "xz")
+ {
+ output = COMPRESS_LZMA;
+ return true;
+ }
+ else if (input_lc == "bz2" || input_lc == "bzip2")
+ {
+ output = COMPRESS_BZIP2;
+ return true;
+ }
+ else if (input_lc == "unknown")
+ {
+ output = COMPRESS_UNKNOWN;
+ return true;
+ }
+ else
+ return false;
+}
+
+// stringify HTIO enum types
+template<>
+std::string to_string<Strand>(Strand arg)
+{
+ switch (arg)
+ {
+ case STRAND_UNKNOWN:
+ return "unknown";
+ case STRAND_FWD:
+ return "forward";
+ case STRAND_REV:
+ return "reverse";
+ default:
+ abort();
+ }
+}
+
+template<>
+std::string to_string<SeqFormat>(SeqFormat arg)
+{
+ switch (arg)
+ {
+ case FORMAT_UNKNOWN:
+ return "unknown";
+ case FORMAT_FASTQ:
+ return "fastq";
+ case FORMAT_FASTA:
+ return "fasta";
+ default:
+ abort();
+ }
+}
+
+template<>
+std::string to_string<HeaderFormat>(HeaderFormat arg)
+{
+ switch (arg)
+ {
+ case HEADER_UNKNOWN:
+ return "unknown";
+ case HEADER_PRI_1_8:
+ return "pri_casava1.8";
+ case HEADER_1_8:
+ return "casava1.8";
+ default:
+ abort();
+ }
+}
+
+template<>
+std::string to_string<QualityEncode>(QualityEncode arg)
+{
+ switch (arg)
+ {
+ case ENCODE_UNKNOWN:
+ return "unknown";
+ case ENCODE_SANGER:
+ return "sanger";
+ case ENCODE_SOLEXA:
+ return "solexa";
+ case ENCODE_ILLUMINA:
+ return "illumina";
+ case ENCODE_CASAVA_1_8:
+ return "casava1.8";
+ default:
+ abort();
+ }
+}
+
+template<>
+std::string to_string<CompressFormat>(CompressFormat arg)
+{
+ switch (arg)
+ {
+ case COMPRESS_PLAIN:
+ return "plain";
+ case COMPRESS_GZIP:
+ return "gzip";
+ case COMPRESS_LZMA:
+ return "lzma";
+ case COMPRESS_BZIP2:
+ return "bzip2";
+ case COMPRESS_UNKNOWN:
+ return "unknown";
+ default:
+ abort();
+ }
+}
+
+
+} // namespace htio2
diff --git a/src/htio2/Cast.h b/src/htio2/Cast.h
new file mode 100644
index 0000000..bb715a3
--- /dev/null
+++ b/src/htio2/Cast.h
@@ -0,0 +1,103 @@
+#ifndef HTIO2_CAST_H
+#define HTIO2_CAST_H
+
+#include <sstream>
+
+#include "htio2/Enum.h"
+
+namespace htio2
+{
+
+template <typename T>
+bool from_string(const std::string& input, T& output);
+
+template <>
+inline bool from_string<std::string>(const std::string& input, std::string& output)
+{
+ output = input;
+ return true;
+}
+
+template <>
+bool from_string<bool>(const std::string& input, bool& output);
+
+// cast to signed integers
+template <>
+bool from_string<short>(const std::string& input, short& output);
+
+template <>
+bool from_string<int>(const std::string& input, int& output);
+
+template <>
+bool from_string<long>(const std::string& input, long& output);
+
+template <>
+bool from_string<long long>(const std::string& input, long long& output);
+
+// cast to unsigned integers
+template <>
+bool from_string<unsigned short>(const std::string& input, unsigned short& output);
+
+template <>
+bool from_string<unsigned int>(const std::string& input, unsigned int& output);
+
+template <>
+bool from_string<unsigned long>(const std::string& input, unsigned long& output);
+
+template <>
+bool from_string<unsigned long long>(const std::string& input, unsigned long long& output);
+
+// cast to floating points
+template <>
+bool from_string<float>(const std::string& input, float& output);
+
+template <>
+bool from_string<double>(const std::string& input, double& output);
+
+template <>
+bool from_string<long double>(const std::string& input, long double& output);
+
+// cast to HTIO enum types
+template<>
+bool from_string<Strand>(const std::string& input, Strand& output);
+
+template<>
+bool from_string<SeqFormat>(const std::string& input, SeqFormat& output);
+
+template<>
+bool from_string<HeaderFormat>(const std::string& input, HeaderFormat& output);
+
+template<>
+bool from_string<QualityEncode>(const std::string& input, QualityEncode& output);
+
+template<>
+bool from_string<CompressFormat>(const std::string& input, CompressFormat& output);
+
+// stringify primitive types
+template <typename T>
+std::string to_string(T input)
+{
+ std::ostringstream result;
+ result << input;
+ return result.str();
+}
+
+// stringify HTIO enum types
+template<>
+std::string to_string<Strand>(Strand input);
+
+template<>
+std::string to_string<SeqFormat>(SeqFormat input);
+
+template<>
+std::string to_string<HeaderFormat>(HeaderFormat input);
+
+template<>
+std::string to_string<QualityEncode>(QualityEncode input);
+
+template<>
+std::string to_string<CompressFormat>(CompressFormat input);
+
+} // namespace htio2
+
+#endif // HTIO2_CAST_H
diff --git a/src/htio2/Enum.cpp b/src/htio2/Enum.cpp
new file mode 100644
index 0000000..1504bff
--- /dev/null
+++ b/src/htio2/Enum.cpp
@@ -0,0 +1,12 @@
+#include "htio2/Enum.h"
+#include <cstdlib>
+#include <stdexcept>
+
+using namespace std;
+
+namespace htio2
+{
+
+
+
+} // namespace htio2
diff --git a/src/htio2/Enum.h b/src/htio2/Enum.h
new file mode 100644
index 0000000..75aae05
--- /dev/null
+++ b/src/htio2/Enum.h
@@ -0,0 +1,58 @@
+#ifndef HTIO2_ENUMS_H
+#define HTIO2_ENUMS_H
+
+#include <string>
+
+namespace htio2
+{
+
+typedef enum
+{
+ STRAND_UNKNOWN = 0,
+ STRAND_FWD = 1,
+ STRAND_REV = 2,
+} Strand;
+
+typedef enum
+{
+ HEADER_UNKNOWN = 0,
+ HEADER_PRI_1_8 = 1, ///< header format prior to CASAVA 1.8
+ HEADER_1_8 = 2, ///< header format by CASAVA 1.8
+} HeaderFormat;
+
+typedef enum
+{
+ ENCODE_UNKNOWN = 0,
+ ENCODE_SANGER = 1, ///< 0 to 93 using ASCII 33 to 126
+ ENCODE_SOLEXA = 2, ///< -5 to 62 using ASCII 59 to 126
+ ENCODE_ILLUMINA = 3, ///< 0 to 62 using ASCII 64 to 126
+ ENCODE_CASAVA_1_8 = 4, ///< 2 to 40 using ASCII 35 to 73
+} QualityEncode;
+
+typedef enum
+{
+ FORMAT_UNKNOWN = 0,
+ FORMAT_FASTQ = 1,
+ FORMAT_FASTA = 2,
+} SeqFormat;
+
+typedef enum
+{
+ COMPRESS_UNKNOWN = 0,
+ COMPRESS_PLAIN = 1,
+ COMPRESS_GZIP = 2,
+ COMPRESS_BZIP2 = 3,
+ COMPRESS_LZMA = 4,
+} CompressFormat;
+
+typedef enum
+{
+ READ,
+ WRITE,
+ APPEND
+} IOMode;
+
+} // namespace htio2
+
+#endif /* HTIO2_ENUMS_H */
+
diff --git a/src/htio2/Error.cpp b/src/htio2/Error.cpp
new file mode 100644
index 0000000..7831a32
--- /dev/null
+++ b/src/htio2/Error.cpp
@@ -0,0 +1,71 @@
+#include "htio2/Error.h"
+#include <sstream>
+#include "htio2/Cast.h"
+
+namespace htio2
+{
+
+InvalidQualityEncode::InvalidQualityEncode(QualityEncode encode)
+: std::invalid_argument(to_string(encode))
+{ }
+
+InvalidQualityEncode::~InvalidQualityEncode() throw ()
+{ }
+
+InvalidHeaderFormat::InvalidHeaderFormat(HeaderFormat format)
+: std::invalid_argument(to_string(format))
+{ }
+
+InvalidHeaderFormat::~InvalidHeaderFormat() throw ()
+{ }
+
+InvalidCompressFormat::InvalidCompressFormat(CompressFormat comp)
+: std::invalid_argument(to_string(comp))
+{ }
+
+InvalidCompressFormat::~InvalidCompressFormat() throw ()
+{ }
+
+InvalidSeqFormat::InvalidSeqFormat(SeqFormat format)
+: std::invalid_argument(to_string(format))
+{ }
+
+InvalidSeqFormat::~InvalidSeqFormat() throw ()
+{ }
+
+InvalidRevcom::InvalidRevcom(const std::string& seq)
+: std::invalid_argument(seq)
+{ }
+
+InvalidRevcom::~InvalidRevcom() throw ()
+{ }
+
+std::string _format_file_message(const std::string& content, size_t offset)
+{
+ std::ostringstream buffer;
+ buffer << "invalid file content at offset " << offset << ": " << content;
+ return buffer.str();
+}
+
+InvalidFileContent::InvalidFileContent(const std::string& content, size_t offset)
+: std::runtime_error(_format_file_message(content, offset))
+{ }
+
+InvalidFileContent::~InvalidFileContent() throw ()
+{ }
+
+std::string _format_kmer_message_(size_t size, size_t limit)
+{
+ std::ostringstream buffer;
+ buffer << "kmer size " << size << " exceeds limit " << limit;
+ return buffer.str();
+}
+
+InvalidKmerSize::InvalidKmerSize(size_t size, size_t limit)
+ : std::runtime_error(_format_kmer_message_(size, limit))
+{ }
+
+InvalidKmerSize::~InvalidKmerSize() throw()
+{ }
+
+} // namespace htio2
diff --git a/src/htio2/Error.h b/src/htio2/Error.h
new file mode 100644
index 0000000..ec53e7d
--- /dev/null
+++ b/src/htio2/Error.h
@@ -0,0 +1,63 @@
+#ifndef HTIO2_ERROR_H
+#define HTIO2_ERROR_H
+
+#include <stdexcept>
+
+#include "htio2/Enum.h"
+
+namespace htio2
+{
+
+class InvalidQualityEncode : public std::invalid_argument
+{
+public:
+ InvalidQualityEncode(QualityEncode encode);
+ virtual ~InvalidQualityEncode() throw ();
+};
+
+class InvalidHeaderFormat : public std::invalid_argument
+{
+public:
+ InvalidHeaderFormat(HeaderFormat format);
+ virtual ~InvalidHeaderFormat() throw ();
+};
+
+class InvalidCompressFormat : public std::invalid_argument
+{
+public:
+ InvalidCompressFormat(CompressFormat comp);
+ virtual ~InvalidCompressFormat() throw ();
+};
+
+class InvalidSeqFormat : public std::invalid_argument
+{
+public:
+ InvalidSeqFormat(SeqFormat format);
+ virtual ~InvalidSeqFormat() throw ();
+};
+
+class InvalidRevcom : public std::invalid_argument
+{
+public:
+ InvalidRevcom(const std::string& seq);
+ virtual ~InvalidRevcom() throw ();
+};
+
+class InvalidFileContent : public std::runtime_error
+{
+public:
+ InvalidFileContent(const std::string& content, size_t offset);
+ virtual ~InvalidFileContent() throw ();
+};
+
+class InvalidKmerSize: public std::runtime_error
+{
+public:
+ InvalidKmerSize(size_t size, size_t limit);
+ virtual ~InvalidKmerSize() throw();
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_ERROR_H */
+
diff --git a/src/htio2/FastaIO.cpp b/src/htio2/FastaIO.cpp
new file mode 100644
index 0000000..b4bc9b2
--- /dev/null
+++ b/src/htio2/FastaIO.cpp
@@ -0,0 +1,177 @@
+/*
+ * File: FastaParser.cpp
+ * Author: yangxi
+ *
+ * Created on December 19, 2012, 11:24 AM
+ */
+
+#include "htio2/FastaIO.h"
+#include "htio2/SimpleSeq.h"
+#include "htio2/Error.h"
+#include "htio2/FileHandle.h"
+#include "htio2/FastqSeq.h"
+
+using namespace std;
+
+namespace htio2
+{
+
+FastaIO::FastaIO(const std::string& filename, IOMode mode, CompressFormat comp) : SeqIO(filename, mode, comp)
+{
+ init_buffer();
+}
+
+FastaIO::FastaIO(FileHandle* handle) : SeqIO(handle)
+{
+ init_buffer();
+}
+
+FastaIO::FastaIO(FILE* handle, bool auto_close) : SeqIO(handle, auto_close)
+{
+ init_buffer();
+}
+
+FastaIO::FastaIO(gzFile handle, bool auto_close) : SeqIO(handle, auto_close)
+{
+ init_buffer();
+}
+
+FastaIO::~FastaIO()
+{
+}
+
+void FastaIO::seek(off_t offset, int whence)
+{
+ if (whence == SEEK_SET)
+ {
+ handle_offset = offset;
+ handle->seek(offset, SEEK_SET);
+ }
+ else if (whence == SEEK_CUR)
+ {
+ handle->seek(handle_offset, SEEK_SET);
+ handle->seek(offset, SEEK_CUR);
+ handle_offset += offset;
+ }
+ else if (whence == SEEK_END)
+ {
+ handle->seek(0, SEEK_END);
+ handle_offset = handle->tell() + offset;
+ handle->seek(offset, SEEK_END);
+ }
+ else
+ throw runtime_error("invalid seek whence");
+
+ handle->read_line(buffer);
+}
+
+off_t FastaIO::tell() const
+{
+ return handle_offset;
+}
+
+bool FastaIO::next_seq(SimpleSeq& result)
+{
+ result.id.clear();
+ result.desc.clear();
+ result.seq.clear();
+
+ //
+ // parse header line
+ // the header line should already be read to buffer
+ //
+ if (!buffer.length()) return false;
+
+ // find the position of first space
+ size_t i_id_end = buffer.find_first_of(" \t");
+
+ if (i_id_end != string::npos)
+ {
+ // assign ID
+ result.id.assign(buffer, 1, i_id_end - 1);
+
+ // find the position of desc
+ size_t i_desc_begin = buffer.find_first_not_of(" \t", i_id_end);
+ if (i_desc_begin != string::npos)
+ {
+ result.desc.assign(buffer, i_desc_begin, string::npos);
+ }
+ }
+ else
+ {
+ // no space, the whole line after ">" is ID
+ result.id.assign(buffer, 1, string::npos);
+ }
+
+ //
+ // get sequence
+ //
+ while (1)
+ {
+ // read a line
+ handle_offset = handle->tell();
+ if (!handle->read_line(buffer)) break;
+
+ // break if we met next record
+ if (buffer[0] == '>')
+ {
+ // ensure the position is at the start of header line
+ break;
+ }
+
+ // store current line to sequence, removing spaces and tabs
+ const size_t buffer_len = buffer.length();
+ for (size_t i = 0; i < buffer_len; i++)
+ {
+ switch (buffer[i])
+ {
+ case ' ':
+ case '\t':
+ break;
+ default:
+ result.seq.push_back(buffer[i]);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool FastaIO::next_seq(FastqSeq& result)
+{
+ bool re = this->next_seq(static_cast<SimpleSeq&> (result));
+ result.quality.resize(result.seq.length(), 33 + 40);
+ return re;
+}
+
+void FastaIO::write_seq(const SimpleSeq& seq)
+{
+ handle->write_line(string(">") + seq.id + " " + seq.desc);
+ for (int i = 0; i < seq.seq.length(); i += 60)
+ handle->write_line(seq.seq.substr(i, 60));
+ handle_offset = handle->tell();
+}
+
+void FastaIO::write_seq(const FastqSeq& seq)
+{
+ write_seq(static_cast<const SimpleSeq&> (seq));
+}
+
+void FastaIO::init_buffer()
+{
+ while (1)
+ {
+ handle_offset = handle->tell();
+ if (!handle->read_line(buffer)) break;
+
+ if (buffer.length())
+ {
+ if (buffer[0] == '>')
+ break;
+ else
+ throw InvalidFileContent(buffer, handle->tell());
+ }
+ }
+}
+
+} //namespace htio2
diff --git a/src/htio2/FastaIO.h b/src/htio2/FastaIO.h
new file mode 100644
index 0000000..dcbb26e
--- /dev/null
+++ b/src/htio2/FastaIO.h
@@ -0,0 +1,104 @@
+/*
+ * File: FastaParser.h
+ * Author: yangxi
+ *
+ * Created on December 19, 2012, 11:24 AM
+ */
+
+#ifndef HTIO2_FASTA_IO_H
+#define HTIO2_FASTA_IO_H
+
+#include "htio2/SeqIO.h"
+
+namespace htio2
+{
+
+class FastaIO;
+
+class FastaIO : public SeqIO
+{
+public:
+ typedef htio2::SmartPtr<FastaIO> Ptr;
+ typedef htio2::SmartPtr<const FastaIO> ConstPtr;
+public:
+ /**
+ * create sequence IO object by file name
+ * @param file file to open
+ * @param mode read/write/append
+ * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
+ */
+ FastaIO(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);
+
+ /**
+ * create sequence IO object from HTIO file handle object
+ * @param handle
+ */
+ FastaIO(FileHandle* handle);
+
+ /**
+ * create sequence IO object from C standard file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
+ */
+ FastaIO(FILE* handle, bool auto_close = true);
+
+ /**
+ * create sequence IO object from Zlib file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
+ */
+ FastaIO(gzFile handle, bool auto_close = true);
+ virtual ~FastaIO();
+
+ /**
+ * Seek to a file offset.
+ * It must be ensured that the offset is always on the beginning of a FASTA entry.
+ * The offset can be different with the wrapped FileHandle's offset.
+ * See implementation of next_seq() for detail.
+ * @param offset
+ * @param whence 0 for absolute, 1 for relative
+ */
+ virtual void seek(off_t offset, int whence = SEEK_SET) override;
+
+ /**
+ * get the current file offset
+ * The offset can be different with the wrapped FileHandle's offset.
+ * See implementation of next_seq() for detail.
+ * @return file offset that is on the beginning of a FASTA entry.
+ */
+ virtual off_t tell() const override;
+
+ /**
+ * read one sequence
+ * @param result
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(SimpleSeq& result) override;
+
+ /**
+ * Read one sequence with quality. The qualities are set to 33+40.
+ * @param result
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(FastqSeq& result) override;
+
+ /**
+ * write one sequence
+ * @param seq the sequence to be written
+ */
+ virtual void write_seq(const SimpleSeq& seq) override;
+
+ virtual void write_seq(const FastqSeq& seq) override;
+protected:
+ /**
+ * The FastaIO guarantee that it won't seek while reading and writing.
+ * However, it could know the position of a record after the header line was read.
+ * Thus we need these facilities to record the file offset before the header line.
+ */
+ off_t handle_offset;
+ void init_buffer();
+};
+} // namespace htio2
+
+#endif /* HTIO2_FASTA_IO_H */
+
diff --git a/src/htio2/FastqIO.cpp b/src/htio2/FastqIO.cpp
new file mode 100644
index 0000000..a000d5f
--- /dev/null
+++ b/src/htio2/FastqIO.cpp
@@ -0,0 +1,126 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/Error.h"
+#include "htio2/FileHandle.h"
+#include <zlib.h>
+
+using namespace std;
+
+namespace htio2
+{
+
+FastqIO::FastqIO(const string& file, IOMode mode, CompressFormat comp) : SeqIO(file, mode, comp)
+{
+}
+
+FastqIO::FastqIO(FileHandle* handle) : SeqIO(handle)
+{
+}
+
+FastqIO::FastqIO(FILE* handle, bool auto_close) : SeqIO(handle, auto_close)
+{
+}
+
+FastqIO::FastqIO(gzFile handle, bool auto_close) : SeqIO(handle, auto_close)
+{
+}
+
+FastqIO::~FastqIO()
+{
+}
+
+bool FastqIO::next_seq(FastqSeq& output)
+{
+ return read_one_seq(output.id, output.desc, output.seq, output.quality);
+}
+
+bool FastqIO::next_seq(SimpleSeq& output)
+{
+ static std::string null;
+ return read_one_seq(output.id, output.desc, output.seq, null);
+}
+
+void FastqIO::write_seq(const FastqSeq& seq)
+{
+ handle->write_line("@" + seq.id + " " + seq.desc);
+ handle->write_line(seq.seq);
+ handle->write_line("+");
+ handle->write_line(seq.quality);
+}
+
+void FastqIO::write_seq(const SimpleSeq& seq)
+{
+ handle->write_line("@" + seq.id + " " + seq.desc);
+ handle->write_line(seq.seq);
+ handle->write_line("+");
+ handle->write_line(std::string(seq.length(), 'I'));
+}
+
+bool FastqIO::read_one_seq(std::string& id, std::string& desc, std::string& seq, std::string& qual)
+{
+ int32_t line_got = 0;
+
+ while (1)
+ {
+ bool re = handle->read_line(buffer);
+
+
+ if (!re) break;
+
+ if (line_got == 0)
+ {
+ if (buffer.length() == 0) continue;
+ line_got++;
+
+ size_t first_space = buffer.find_first_of(" \t");
+ size_t desc_begin = buffer.find_first_not_of(" \t", first_space);
+ id.assign(buffer, 1, first_space - 1);
+
+ if (desc_begin == string::npos)
+ desc = "";
+ else
+ desc.assign(buffer, desc_begin, string::npos);
+ }
+ else if (line_got == 1)
+ {
+ line_got++;
+ seq = buffer;
+ }
+ else if (line_got == 2)
+ {
+ line_got++;
+ if (buffer[0] != '+')
+ throw InvalidFileContent(buffer, handle->tell());
+ }
+ else if (line_got == 3)
+ {
+ line_got++;
+ qual = buffer;
+ if (seq.length() != buffer.length())
+ throw InvalidFileContent(buffer, handle->tell());
+ break;
+ }
+ }
+
+ if ((line_got != 4) && (line_got != 0))
+ throw InvalidFileContent("incomplete FASTQ record", handle->tell());
+
+ return line_got > 0;
+}
+
+} // namespace htio2
diff --git a/src/htio2/FastqIO.h b/src/htio2/FastqIO.h
new file mode 100644
index 0000000..3877f1b
--- /dev/null
+++ b/src/htio2/FastqIO.h
@@ -0,0 +1,95 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_FASTQ_IO_H
+#define HTIO2_FASTQ_IO_H
+
+#include "htio2/SeqIO.h"
+
+namespace htio2
+{
+
+class FastqSeq;
+class FastqIO;
+
+class FastqIO : public SeqIO
+{
+public:
+ typedef SmartPtr<FastqIO> Ptr;
+ typedef SmartPtr<const FastqIO> ConstPtr;
+
+public:
+ /**
+ * create sequence IO object by file name
+ * @param file file to open
+ * @param mode read/write/append
+ * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
+ */
+ FastqIO(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);
+
+ /**
+ * create sequence IO object from HTIO file handle object
+ * @param handle
+ */
+ FastqIO(FileHandle* handle);
+
+ /**
+ * create sequence IO object from C file handle
+ * @param handle
+ * @param auto_close if set to true, close the handle when sequence IO object is destroyed
+ */
+ FastqIO(FILE* handle, bool auto_close = true);
+
+ /**
+ * create sequence IO object from Zlib file handle
+ * @param handle
+ * @param auto_close if set to true, close the handle when sequence IO object is destroyed
+ */
+ FastqIO(gzFile handle, bool auto_close = true);
+ virtual ~FastqIO();
+
+ /**
+ * read one sequence.
+ * @param output
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(FastqSeq& output);
+
+ /**
+ * read one sequence with quality
+ * @param output
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(SimpleSeq& output);
+
+ /**
+ * write one sequence
+ * @param seq seq to write
+ */
+ virtual void write_seq(const FastqSeq& seq);
+
+ /**
+ * Write one sequence. Quality will be filled with 'I'
+ * @param output
+ */
+ virtual void write_seq(const SimpleSeq& seq);
+
+private:
+ bool read_one_seq(std::string& id, std::string& desc, std::string& seq, std::string& qual);
+};
+
+} // namespace htio2
+
+#endif // HTIO2_FASTQ_IO_H
diff --git a/src/htio2/FastqSeq.cpp b/src/htio2/FastqSeq.cpp
new file mode 100644
index 0000000..1e1f5b8
--- /dev/null
+++ b/src/htio2/FastqSeq.cpp
@@ -0,0 +1,42 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#include "htio2/FastqSeq.h"
+
+using namespace std;
+
+namespace htio2
+{
+
+FastqSeq::FastqSeq()
+{
+}
+
+FastqSeq::~FastqSeq()
+{
+}
+
+void FastqSeq::revcom(FastqSeq& result) const
+{
+ SimpleSeq::revcom(result);
+ result.quality.assign(quality.rbegin(), quality.rend());
+}
+
+void FastqSeq::subseq(FastqSeq& result, size_t start, size_t length) const
+{
+ SimpleSeq::subseq(result, start, length);
+ result.quality.assign(quality, start, length);
+}
+
+} // namespace htio2
diff --git a/src/htio2/FastqSeq.h b/src/htio2/FastqSeq.h
new file mode 100644
index 0000000..b1d8c0d
--- /dev/null
+++ b/src/htio2/FastqSeq.h
@@ -0,0 +1,66 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_FASTQ_SEQ_H
+#define HTIO2_FASTQ_SEQ_H
+
+#include <htio2/SimpleSeq.h>
+
+namespace htio2
+{
+
+/**
+ * @brief sequence with ASCII quality
+ */
+class FastqSeq : public SimpleSeq
+{
+public:
+ typedef SmartPtr<FastqSeq> Ptr;
+ typedef SmartPtr<const FastqSeq> ConstPtr;
+
+public:
+ /**
+ * create an empty sequence object
+ */
+ FastqSeq();
+
+ virtual ~FastqSeq();
+
+ /**
+ * generate reverse complement sequence
+ * @param result
+ */
+ void revcom(FastqSeq& result) const;
+
+
+ /**
+ * Get part of the sequence. The quality is truncated correspondingly.
+ * @param result store the sub-sequence
+ * @param start start of the sub-sequence. 0 for the first base
+ * @param length length of the sub-sequence. std::string::npos to get everyting until the end.
+ */
+ void subseq(FastqSeq& result, size_t start, size_t length = std::string::npos) const;
+
+ /**
+ * Stringified quality score. If you want quality in numbers, see function
+ * "decode_quality" in header "QualityUtil.h".
+ */
+ std::string quality;
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_FASTQ_SEQ_H */
+
diff --git a/src/htio2/FileHandle.cpp b/src/htio2/FileHandle.cpp
new file mode 100644
index 0000000..2a7e7cd
--- /dev/null
+++ b/src/htio2/FileHandle.cpp
@@ -0,0 +1,30 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/FileHandle.h"
+
+namespace htio2
+{
+
+FileHandle::FileHandle()
+{
+
+}
+
+FileHandle::~FileHandle()
+{
+}
+
+} // namespace htio2
diff --git a/src/htio2/FileHandle.h b/src/htio2/FileHandle.h
new file mode 100644
index 0000000..68f1a93
--- /dev/null
+++ b/src/htio2/FileHandle.h
@@ -0,0 +1,94 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_FILE_HANDLE_H
+#define HTIO2_FILE_HANDLE_H
+
+#include <string>
+
+#include "htio2/RefCounted.h"
+#include "htio2/Enum.h"
+
+namespace htio2
+{
+
+#define LINE_END_CR 13
+#define LINE_END_LF 10
+
+inline const char* get_io_mode_str(IOMode mode)
+{
+ switch (mode)
+ {
+ case READ:
+ return "rb";
+ case WRITE:
+ return "wb";
+ case APPEND:
+ return "ab";
+ default:
+ return 0;
+ }
+}
+
+/**
+ * An abstract base class for file handles.
+ */
+class FileHandle : public RefCounted
+{
+public:
+ typedef SmartPtr<FileHandle> Ptr;
+ typedef SmartPtr<const FileHandle> ConstPtr;
+
+public:
+ FileHandle();
+ virtual ~FileHandle();
+
+ /**
+ * Read one line. The end-of-line character can be CR, LF and CRLF.
+ * @param buffer
+ * @return true if get a line, false if reached end of file.
+ */
+ virtual bool read_line(std::string& buffer) = 0;
+
+ /**
+ * Write one line. The end-of-line character is decided by the system.
+ * @param content the content to be written
+ */
+ virtual void write_line(const std::string& content) = 0;
+
+ /**
+ * Seek to a file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @param offset
+ * @param whence 0 for absolute, 1 for relative
+ */
+ virtual void seek(off_t offset, int whence = SEEK_SET) = 0;
+
+ /**
+ * Get the current file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @return offset
+ */
+ virtual off_t tell() const = 0;
+
+private:
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_FILE_HANDLE_H */
+
diff --git a/src/htio2/FormatUtil.cpp b/src/htio2/FormatUtil.cpp
new file mode 100644
index 0000000..215050c
--- /dev/null
+++ b/src/htio2/FormatUtil.cpp
@@ -0,0 +1,75 @@
+#include "htio2/FormatUtil.h"
+
+#include "htio2/Error.h"
+#include "htio2/PlainFileHandle.h"
+#include "htio2/GzipFileHandle.h"
+
+using namespace std;
+
+namespace htio2
+{
+
+CompressFormat guess_compress_by_name(const std::string& file)
+{
+ if (file.rfind(".gz") != std::string::npos) return COMPRESS_GZIP;
+ else return COMPRESS_PLAIN;
+}
+
+SeqFormat guess_format_by_name_and_content(const std::string& file, CompressFormat comp)
+{
+ SeqFormat re = guess_format_by_name(file);
+ if (re == FORMAT_UNKNOWN)
+ {
+ FileHandle* handle = 0;
+ if (comp == COMPRESS_GZIP)
+ handle = new GzipFileHandle(file.c_str(), READ);
+ else if (comp == COMPRESS_PLAIN)
+ handle = new PlainFileHandle(file.c_str(), READ);
+ else
+ throw InvalidCompressFormat(comp);
+
+ re = guess_format_by_content(*handle);
+ delete handle;
+ }
+ return re;
+}
+
+SeqFormat guess_format_by_name(const std::string& file)
+{
+ if (file.rfind(".fastq") != string::npos ||
+ file.rfind(".fq") != string::npos)
+ {
+ return FORMAT_FASTQ;
+ }
+ else if (file.rfind(".fasta") != string::npos ||
+ file.rfind(".fas") != string::npos ||
+ file.rfind(".fa") != string::npos ||
+ file.rfind(".faa") != string::npos ||
+ file.rfind(".fna") != string::npos)
+ {
+ return FORMAT_FASTA;
+ }
+ else
+ {
+ return FORMAT_UNKNOWN;
+ }
+}
+
+SeqFormat guess_format_by_content(FileHandle& handle)
+{
+ // read first line, guess format
+ string line;
+ handle.read_line(line);
+
+ SeqFormat format;
+ if (line[0] == '>')
+ format = FORMAT_FASTA;
+ else if (line[0] == '@')
+ format = FORMAT_FASTQ;
+ else
+ format = FORMAT_UNKNOWN;
+
+ return format;
+}
+
+} // namespace htio2
diff --git a/src/htio2/FormatUtil.h b/src/htio2/FormatUtil.h
new file mode 100644
index 0000000..7846ffd
--- /dev/null
+++ b/src/htio2/FormatUtil.h
@@ -0,0 +1,22 @@
+#ifndef HTIO2_FORMAT_UTIL_H
+#define HTIO2_FORMAT_UTIL_H
+
+#include <string>
+#include <htio2/Enum.h>
+
+namespace htio2
+{
+
+class FileHandle;
+
+CompressFormat guess_compress_by_name(const std::string& file);
+
+SeqFormat guess_format_by_name_and_content(const std::string& file, CompressFormat comp);
+SeqFormat guess_format_by_name(const std::string& file);
+SeqFormat guess_format_by_content(FileHandle& handle);
+
+
+} // namespace htio2
+
+#endif /* HTIO2_FORMAT_UTIL_H */
+
diff --git a/src/htio2/GzipFileHandle.cpp b/src/htio2/GzipFileHandle.cpp
new file mode 100644
index 0000000..7ae16ab
--- /dev/null
+++ b/src/htio2/GzipFileHandle.cpp
@@ -0,0 +1,112 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/GzipFileHandle.h"
+#include "htio2/Error.h"
+
+#include <cstring>
+#include <cerrno>
+#include <cstdio>
+#include <zlib.h>
+
+using namespace std;
+
+namespace htio2
+{
+
+GzipFileHandle::GzipFileHandle(const string& file, IOMode mode) : auto_close(true)
+{
+ handle = gzopen(file.c_str(), get_io_mode_str(mode));
+ if (handle == 0)
+ {
+ const char* msg = strerror(errno);
+ throw runtime_error(string(msg));
+ }
+ offset = gztell(handle);
+ curr_chr = gzgetc(handle);
+}
+
+GzipFileHandle::GzipFileHandle(gzFile handle, bool auto_close) : auto_close(auto_close)
+{
+ offset = gztell(handle);
+ curr_chr = gzgetc(handle);
+}
+
+GzipFileHandle::~GzipFileHandle()
+{
+ if (auto_close) gzclose(handle);
+}
+
+bool GzipFileHandle::read_line(std::string& buffer)
+{
+ buffer.clear();
+ if (curr_chr == EOF) return false;
+
+ while (1)
+ {
+ switch (curr_chr)
+ {
+ case EOF:
+ goto END;
+ case LINE_END_CR:
+ curr_chr = gzgetc(handle);
+ if (curr_chr == LINE_END_LF) curr_chr = gzgetc(handle);
+ goto END;
+ case LINE_END_LF:
+ curr_chr = gzgetc(handle);
+ goto END;
+ default:
+ buffer.push_back(curr_chr);
+ curr_chr = gzgetc(handle);
+ }
+ }
+
+END:
+ offset = gztell(handle) - 1;
+ return true;
+}
+
+void GzipFileHandle::write_line(const std::string& content)
+{
+ gzwrite(handle, content.data(), content.size());
+ gzputc(handle, '\n');
+ offset = gztell(handle);
+}
+
+void GzipFileHandle::seek(off_t offset, int whence)
+{
+ if (whence == SEEK_SET)
+ {
+ this->offset = offset;
+ gzseek(handle, offset, SEEK_SET);
+ }
+ else if (whence == SEEK_CUR)
+ {
+ gzseek(handle, this->offset, SEEK_SET);
+ gzseek(handle, offset, SEEK_CUR);
+ this->offset += offset;
+ }
+ else
+ throw runtime_error("invalid seek whence");
+
+ curr_chr = gzgetc(handle);
+}
+
+off_t GzipFileHandle::tell() const
+{
+ return offset;
+}
+
+} // namespace htio2
diff --git a/src/htio2/GzipFileHandle.h b/src/htio2/GzipFileHandle.h
new file mode 100644
index 0000000..4905fb2
--- /dev/null
+++ b/src/htio2/GzipFileHandle.h
@@ -0,0 +1,88 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_GZIP_FILE_HANDLE_H
+#define HTIO2_GZIP_FILE_HANDLE_H
+
+#include "htio2/FileHandle.h"
+#include <zlib.h>
+
+namespace htio2
+{
+
+class GzipFileHandle : public FileHandle
+{
+ friend class ::TestFramework;
+public:
+ typedef SmartPtr<GzipFileHandle> Ptr;
+ typedef SmartPtr<const GzipFileHandle> ConstPtr;
+
+public:
+ /**
+ * create by file name and mode
+ * @param file file name
+ * @param mode "rb" for read, "wb" for write
+ */
+ GzipFileHandle(const std::string& file, IOMode mode);
+
+ /**
+ * create from Zlib file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying gzFile will be closed when the object is destroyed
+ */
+ GzipFileHandle(gzFile handle, bool auto_close = true);
+
+ virtual ~GzipFileHandle();
+
+ /**
+ * Read one line. The end-of-line character can be CR, LF and CRLF.
+ * @param buffer
+ * @return true if get a line, false if reached end of file.
+ */
+ virtual bool read_line(std::string& buffer);
+
+ /**
+ * Write one line. The end-of-line character is decided by the system.
+ * @param content
+ */
+ virtual void write_line(const std::string& content);
+
+ /**
+ * Seek to a file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @param offset
+ * @param whence SEEK_SET or 0 for absolute, SEEK_CUR or 1 for relative. Note: SEEK_END is not supported by zlib.
+ */
+ virtual void seek(off_t offset, int whence = SEEK_SET);
+
+ /**
+ * Get the current file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @return offset
+ */
+ virtual off_t tell() const;
+private:
+ gzFile handle;
+ bool auto_close;
+ off_t offset;
+ char curr_chr;
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_GZIP_FILE_HANDLE_H */
+
diff --git a/src/htio2/HeaderUtil.cpp b/src/htio2/HeaderUtil.cpp
new file mode 100644
index 0000000..24b29a7
--- /dev/null
+++ b/src/htio2/HeaderUtil.cpp
@@ -0,0 +1,216 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/HeaderUtil.h"
+#include "htio2/Cast.h"
+#include "htio2/FastqIO.h"
+#include "htio2/SimpleSeq.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/Error.h"
+
+#include "JUCE-3.0.8/JuceHeader.h"
+
+using namespace std;
+using namespace htio2::juce;
+
+namespace htio2
+{
+
+void guess_header_format(const std::string& header,
+ HeaderFormat& format,
+ bool& with_ncbi_additive)
+{
+// printf("header: %s\n", header.c_str());
+ string header_use;
+ if (header[0] == '@') header_use.assign(header, 1, string::npos);
+ else header_use = header;
+
+ StringArray fields;
+ fields.addTokens(String(header_use), " \t");
+
+ // check the existance of NCBI additive part
+ if (fields.size() >= 2 &&
+ fields.strings.getFirst().startsWith("SRR") &&
+ fields.strings.getLast().startsWith("length="))
+ {
+// printf(" with NCBI\n");
+ with_ncbi_additive = true;
+ fields.remove(0);
+ fields.remove(fields.size()-1);
+ }
+ else
+ {
+ with_ncbi_additive = false;
+ }
+
+ // check header format
+ if (fields.size() >= 1)
+ {
+// printf(" check %s\n", fields[0].toRawUTF8());
+ StringArray tokens_f1;
+ tokens_f1.addTokens(fields[0], ":", "");
+// printf(" %d tokens\n", tokens_f1.size());
+
+ int lane = -1;
+ int tile = -1;
+ int x = -1;
+ int y = -1;
+
+ if (tokens_f1.size() == 5 &&
+ from_string<int>(tokens_f1[1].toStdString(), lane) &&
+ from_string<int>(tokens_f1[2].toStdString(), tile) &&
+ from_string<int>(tokens_f1[3].toStdString(), x) &&
+ from_string<int>(tokens_f1[4].toStdString(), y))
+ {
+ format = HEADER_PRI_1_8;
+ }
+ else if (tokens_f1.size() == 7 &&
+ from_string<int>(tokens_f1[3].toStdString(), lane) &&
+ from_string<int>(tokens_f1[4].toStdString(), tile) &&
+ from_string<int>(tokens_f1[5].toStdString(), x) &&
+ from_string<int>(tokens_f1[6].toStdString(), y))
+ {
+ format = HEADER_1_8;
+ }
+ else
+ {
+ format = HEADER_UNKNOWN;
+ }
+ }
+ else
+ {
+ format = HEADER_UNKNOWN;
+ }
+}
+
+size_t guess_header_format(FastqIO& stream, size_t num_to_guess, HeaderFormat& format, bool& with_ncbi_additive)
+{
+ FastqSeq seq;
+ HeaderFormat tmp_format = HEADER_UNKNOWN;
+ bool tmp_ncbi_flag = false;
+
+ size_t num_seq = 0;
+ off_t orig_offset = stream.tell();
+
+ for (; num_seq < num_to_guess; num_seq++)
+ {
+ if (!stream.next_seq(seq)) break;
+ HeaderFormat curr_format;
+ bool curr_ncbi_flag;
+ guess_header_format(seq.id + " " + seq.desc, curr_format, curr_ncbi_flag);
+
+ if (tmp_format == HEADER_UNKNOWN)
+ {
+ tmp_format = curr_format;
+ tmp_ncbi_flag = curr_ncbi_flag;
+ }
+ else
+ {
+ if (tmp_format != curr_format || tmp_ncbi_flag != curr_ncbi_flag)
+ {
+ stream.seek(orig_offset, 0);
+ throw runtime_error("FASTQ content has mixed header format");
+ }
+ }
+ }
+
+ stream.seek(orig_offset, 0);
+ format = tmp_format;
+ with_ncbi_additive = tmp_ncbi_flag;
+ return num_seq;
+}
+
+HeaderParser::HeaderParser(HeaderFormat h_format, bool with_ncbi_additive)
+: format(h_format)
+, with_ncbi_additive(with_ncbi_additive)
+{
+ if (h_format == HEADER_1_8)
+ lane_colon_pos = 3;
+ else if (h_format == HEADER_PRI_1_8)
+ lane_colon_pos = 1;
+ else
+ lane_colon_pos = -1;
+}
+
+void HeaderParser::parse(const string& id, const string& desc)
+{
+ if (lane_colon_pos == -1)
+ {
+ lane = 0;
+ tile = 0;
+ barcode.clear();
+ return;
+ }
+
+ string id_tidy;
+ string desc_tidy;
+ if (with_ncbi_additive)
+ {
+ size_t prefix_end = id.find_first_of(" \t");
+ size_t suffix_begin = desc.find_last_of(" \t");
+ if (prefix_end == string::npos || suffix_begin == string::npos)
+ throw runtime_error("failed to locate NCBI SRA additive in header: " + id + " " + desc);
+
+ size_t tidy_begin = id.find_first_not_of(" \t", prefix_end + 1);
+ size_t tidy_end = desc.find_last_not_of(" \t", suffix_begin - 1);
+
+ id_tidy.assign(id, tidy_begin, string::npos);
+ desc_tidy.assign(desc, 0, tidy_end + 1);
+ }
+ else
+ {
+ id_tidy = id;
+ desc_tidy = desc;
+ }
+
+ //
+ // parse lane and tile
+ //
+ int32_t lane_i_begin = -1;
+ int32_t num_colon = 0;
+
+ for (size_t i = 0; i < id_tidy.size(); i++)
+ {
+ if (id_tidy[i] == ':') num_colon++;
+
+ if (num_colon == lane_colon_pos)
+ {
+ lane_i_begin = i + 1;
+ break;
+ }
+ }
+
+ if (sscanf(id_tidy.c_str() + lane_i_begin, "%d:%d:", &lane, &tile) != 2)
+ throw runtime_error("failed to parse lane and tile in header: " + id_tidy);
+
+ //
+ // parse barcode
+ //
+ if (format == HEADER_1_8)
+ {
+ size_t pos = desc_tidy.find_last_of(':');
+ barcode.assign(desc_tidy, pos + 1, string::npos);
+ }
+ else if (format == HEADER_PRI_1_8)
+ {
+ barcode = "";
+ }
+ else
+ {
+ barcode = "";
+ }
+}
+
+} // namespace htio2
diff --git a/src/htio2/HeaderUtil.h b/src/htio2/HeaderUtil.h
new file mode 100644
index 0000000..b4fb2bd
--- /dev/null
+++ b/src/htio2/HeaderUtil.h
@@ -0,0 +1,72 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_HEADER_UTIL_H
+#define HTIO2_HEADER_UTIL_H
+
+#include "htio2/Enum.h"
+
+namespace htio2
+{
+
+/**
+ * Guess header format from one header.
+ * @param header
+ * @param format header format of the input header
+ * @param with_ncbi_additive will be set to true if the header has information added by NCBI SRA
+ */
+void guess_header_format(const std::string& header, HeaderFormat& format, bool& with_ncbi_additive);
+
+
+class FastqIO;
+
+/**
+ * Guess header format from several input sequences.
+ * @param stream sequences to guess are read from this stream.
+ * @param num_to_guess the amount of sequences to be guessed.
+ * @param format header format of input sequences.
+ * @param with_ncbi_additive will be set to true if the header has information added by NCBI SRA.
+ * @return number of sequences that are actually used to guess.
+ */
+size_t guess_header_format(FastqIO& stream, size_t num_to_guess, HeaderFormat& format, bool& with_ncbi_additive);
+
+class HeaderParser
+{
+public:
+ /**
+ * create a FASTQ header parser
+ * @param h_format the header format
+ * @param with_ncbi_additive whether the header would contain NCBI SRA additional contents.
+ */
+ HeaderParser(HeaderFormat h_format, bool with_ncbi_additive);
+
+ /**
+ * Parse a FASTQ header. The results are stored on the members of HeaderParser object.
+ * @param id the content of FASTQ header before the first block of continuous space
+ * @param desc the content of FASTQ header after the first block of continuous space
+ */
+ void parse(const std::string& id, const std::string& desc);
+
+ HeaderFormat format;
+ bool with_ncbi_additive;
+ int lane_colon_pos;
+ int lane;
+ int tile;
+ std::string barcode;
+};
+
+} // namespace htio2
+
+#endif // HTIO2_HEADER_UTIL_H
diff --git a/src/htio2/JUCE-3.0.8/AppConfig.h b/src/htio2/JUCE-3.0.8/AppConfig.h
new file mode 100644
index 0000000..8eabb6c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/AppConfig.h
@@ -0,0 +1,51 @@
+/*
+
+ IMPORTANT! This file is auto-generated each time you save your
+ project - if you alter its contents, your changes may be overwritten!
+
+ There's a section below where you can add your own custom code safely, and the
+ Introjucer will preserve the contents of that block, but the best way to change
+ any of these definitions is by using the Introjucer's project settings.
+
+ Any commented-out settings will assume their default values.
+
+*/
+
+#ifndef __JUCE_APPCONFIG_YGTDMY__
+#define __JUCE_APPCONFIG_YGTDMY__
+
+//==============================================================================
+// [BEGIN_USER_CODE_SECTION]
+
+// (You can add your own code in this section, and the Introjucer will not overwrite it)
+
+// [END_USER_CODE_SECTION]
+
+//==============================================================================
+#define JUCE_MODULE_AVAILABLE_juce_core 1
+
+//==============================================================================
+// juce_core flags:
+
+#ifndef JUCE_FORCE_DEBUG
+ //#define JUCE_FORCE_DEBUG
+#endif
+
+#ifndef JUCE_LOG_ASSERTIONS
+ //#define JUCE_LOG_ASSERTIONS
+#endif
+
+#ifndef JUCE_CHECK_MEMORY_LEAKS
+ //#define JUCE_CHECK_MEMORY_LEAKS
+#endif
+
+#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+ //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+#endif
+
+#ifndef JUCE_INCLUDE_ZLIB_CODE
+ //#define JUCE_INCLUDE_ZLIB_CODE
+#endif
+
+
+#endif // __JUCE_APPCONFIG_YGTDMY__
diff --git a/src/htio2/JUCE-3.0.8/CMakeLists.txt b/src/htio2/JUCE-3.0.8/CMakeLists.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/htio2/JUCE-3.0.8/JuceHeader.h b/src/htio2/JUCE-3.0.8/JuceHeader.h
new file mode 100644
index 0000000..9f7a1ed
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/JuceHeader.h
@@ -0,0 +1,19 @@
+/*
+
+ IMPORTANT! This file is auto-generated each time you save your
+ project - if you alter its contents, your changes may be overwritten!
+
+ This is the header file that your files should include in order to get all the
+ JUCE library headers. You should avoid including the JUCE headers directly in
+ your own source files, because that wouldn't pick up the correct configuration
+ options for your app.
+
+*/
+
+#ifndef __JUCE_HEADER_H__
+#define __JUCE_HEADER_H__
+
+#include "AppConfig.h"
+#include "modules/juce_core/juce_core.h"
+
+#endif // __JUCE_HEADER_H__
diff --git a/src/htio2/JUCE-3.0.8/ReadMe.txt b/src/htio2/JUCE-3.0.8/ReadMe.txt
new file mode 100644
index 0000000..f6c3564
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/ReadMe.txt
@@ -0,0 +1,12 @@
+
+ Important Note!!
+ ================
+
+The purpose of this folder is to contain files that are auto-generated by the Introjucer,
+and ALL files in this folder will be mercilessly DELETED and completely re-written whenever
+the Introjucer saves your project.
+
+Therefore, it's a bad idea to make any manual changes to the files in here, or to
+put any of your own files in here if you don't want to lose them. (Of course you may choose
+to add the folder's contents to your version-control system so that you can re-merge your own
+modifications after the Introjucer has saved its changes).
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.cpp
new file mode 100644
index 0000000..65b1615
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.cpp
@@ -0,0 +1,235 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+AbstractFifo::AbstractFifo (const int capacity) noexcept
+ : bufferSize (capacity)
+{
+ jassert (bufferSize > 0);
+}
+
+AbstractFifo::~AbstractFifo() {}
+
+int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
+int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady() - 1; }
+
+int AbstractFifo::getNumReady() const noexcept
+{
+ const int vs = validStart.get();
+ const int ve = validEnd.get();
+ return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
+}
+
+void AbstractFifo::reset() noexcept
+{
+ validEnd = 0;
+ validStart = 0;
+}
+
+void AbstractFifo::setTotalSize (int newSize) noexcept
+{
+ jassert (newSize > 0);
+ reset();
+ bufferSize = newSize;
+}
+
+//==============================================================================
+void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
+{
+ const int vs = validStart.get();
+ const int ve = validEnd.value;
+
+ const int freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
+ numToWrite = jmin (numToWrite, freeSpace - 1);
+
+ if (numToWrite <= 0)
+ {
+ startIndex1 = 0;
+ startIndex2 = 0;
+ blockSize1 = 0;
+ blockSize2 = 0;
+ }
+ else
+ {
+ startIndex1 = ve;
+ startIndex2 = 0;
+ blockSize1 = jmin (bufferSize - ve, numToWrite);
+ numToWrite -= blockSize1;
+ blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
+ }
+}
+
+void AbstractFifo::finishedWrite (int numWritten) noexcept
+{
+ jassert (numWritten >= 0 && numWritten < bufferSize);
+ int newEnd = validEnd.value + numWritten;
+ if (newEnd >= bufferSize)
+ newEnd -= bufferSize;
+
+ validEnd = newEnd;
+}
+
+void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
+{
+ const int vs = validStart.value;
+ const int ve = validEnd.get();
+
+ const int numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
+ numWanted = jmin (numWanted, numReady);
+
+ if (numWanted <= 0)
+ {
+ startIndex1 = 0;
+ startIndex2 = 0;
+ blockSize1 = 0;
+ blockSize2 = 0;
+ }
+ else
+ {
+ startIndex1 = vs;
+ startIndex2 = 0;
+ blockSize1 = jmin (bufferSize - vs, numWanted);
+ numWanted -= blockSize1;
+ blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
+ }
+}
+
+void AbstractFifo::finishedRead (int numRead) noexcept
+{
+ jassert (numRead >= 0 && numRead <= bufferSize);
+
+ int newStart = validStart.value + numRead;
+ if (newStart >= bufferSize)
+ newStart -= bufferSize;
+
+ validStart = newStart;
+}
+
+//==============================================================================
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class AbstractFifoTests : public UnitTest
+{
+public:
+ AbstractFifoTests() : UnitTest ("Abstract Fifo") {}
+
+ class WriteThread : public Thread
+ {
+ public:
+ WriteThread (AbstractFifo& f, int* b, Random rng)
+ : Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
+ {
+ startThread();
+ }
+
+ ~WriteThread()
+ {
+ stopThread (5000);
+ }
+
+ void run()
+ {
+ int n = 0;
+
+ while (! threadShouldExit())
+ {
+ int num = random.nextInt (2000) + 1;
+
+ int start1, size1, start2, size2;
+ fifo.prepareToWrite (num, start1, size1, start2, size2);
+
+ jassert (size1 >= 0 && size2 >= 0);
+ jassert (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()));
+ jassert (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize()));
+
+ for (int i = 0; i < size1; ++i)
+ buffer [start1 + i] = n++;
+
+ for (int i = 0; i < size2; ++i)
+ buffer [start2 + i] = n++;
+
+ fifo.finishedWrite (size1 + size2);
+ }
+ }
+
+ private:
+ AbstractFifo& fifo;
+ int* buffer;
+ Random random;
+ };
+
+ void runTest()
+ {
+ beginTest ("AbstractFifo");
+
+ int buffer [5000];
+ AbstractFifo fifo (numElementsInArray (buffer));
+
+ WriteThread writer (fifo, buffer, getRandom());
+
+ int n = 0;
+ Random r = getRandom();
+ r.combineSeed (12345);
+
+ for (int count = 100000; --count >= 0;)
+ {
+ int num = r.nextInt (6000) + 1;
+
+ int start1, size1, start2, size2;
+ fifo.prepareToRead (num, start1, size1, start2, size2);
+
+ if (! (size1 >= 0 && size2 >= 0)
+ && (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()))
+ && (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize())))
+ {
+ expect (false, "prepareToRead returned -ve values");
+ break;
+ }
+
+ bool failed = false;
+
+ for (int i = 0; i < size1; ++i)
+ failed = (buffer [start1 + i] != n++) || failed;
+
+ for (int i = 0; i < size2; ++i)
+ failed = (buffer [start2 + i] != n++) || failed;
+
+ if (failed)
+ {
+ expect (false, "read values were incorrect");
+ break;
+ }
+
+ fifo.finishedRead (size1 + size2);
+ }
+ }
+};
+
+static AbstractFifoTests fifoUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.h
new file mode 100644
index 0000000..02feac7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_AbstractFifo.h
@@ -0,0 +1,220 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ABSTRACTFIFO_H_INCLUDED
+#define JUCE_ABSTRACTFIFO_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Encapsulates the logic required to implement a lock-free FIFO.
+
+ This class handles the logic needed when building a single-reader, single-writer FIFO.
+
+ It doesn't actually hold any data itself, but your FIFO class can use one of these to manage
+ its position and status when reading or writing to it.
+
+ To use it, you can call prepareToWrite() to determine the position within your own buffer that
+ an incoming block of data should be stored, and prepareToRead() to find out when the next
+ outgoing block should be read from.
+
+ e.g.
+ @code
+ class MyFifo
+ {
+ public:
+ MyFifo() : abstractFifo (1024)
+ {
+ }
+
+ void addToFifo (const int* someData, int numItems)
+ {
+ int start1, size1, start2, size2;
+ abstractFifo.prepareToWrite (numItems, start1, size1, start2, size2);
+
+ if (size1 > 0)
+ copySomeData (myBuffer + start1, someData, size1);
+
+ if (size2 > 0)
+ copySomeData (myBuffer + start2, someData + size1, size2);
+
+ abstractFifo.finishedWrite (size1 + size2);
+ }
+
+ void readFromFifo (int* someData, int numItems)
+ {
+ int start1, size1, start2, size2;
+ abstractFifo.prepareToRead (numSamples, start1, size1, start2, size2);
+
+ if (size1 > 0)
+ copySomeData (someData, myBuffer + start1, size1);
+
+ if (size2 > 0)
+ copySomeData (someData + size1, myBuffer + start2, size2);
+
+ abstractFifo.finishedRead (size1 + size2);
+ }
+
+ private:
+ AbstractFifo abstractFifo;
+ int myBuffer [1024];
+ };
+ @endcode
+*/
+class JUCE_API AbstractFifo
+{
+public:
+ //==============================================================================
+ /** Creates a FIFO to manage a buffer with the specified capacity. */
+ AbstractFifo (int capacity) noexcept;
+
+ /** Destructor */
+ ~AbstractFifo();
+
+ //==============================================================================
+ /** Returns the total size of the buffer being managed. */
+ int getTotalSize() const noexcept;
+
+ /** Returns the number of items that can currently be added to the buffer without it overflowing. */
+ int getFreeSpace() const noexcept;
+
+ /** Returns the number of items that can currently be read from the buffer. */
+ int getNumReady() const noexcept;
+
+ /** Clears the buffer positions, so that it appears empty. */
+ void reset() noexcept;
+
+ /** Changes the buffer's total size.
+ Note that this isn't thread-safe, so don't call it if there's any danger that it
+ might overlap with a call to any other method in this class!
+ */
+ void setTotalSize (int newSize) noexcept;
+
+ //==============================================================================
+ /** Returns the location within the buffer at which an incoming block of data should be written.
+
+ Because the section of data that you want to add to the buffer may overlap the end
+ and wrap around to the start, two blocks within your buffer are returned, and you
+ should copy your data into the first one, with any remaining data spilling over into
+ the second.
+
+ If the number of items you ask for is too large to fit within the buffer's free space, then
+ blockSize1 + blockSize2 may add up to a lower value than numToWrite. If this happens, you
+ may decide to keep waiting and re-trying the method until there's enough space available.
+
+ After calling this method, if you choose to write your data into the blocks returned, you
+ must call finishedWrite() to tell the FIFO how much data you actually added.
+
+ e.g.
+ @code
+ void addToFifo (const int* someData, int numItems)
+ {
+ int start1, size1, start2, size2;
+ prepareToWrite (numItems, start1, size1, start2, size2);
+
+ if (size1 > 0)
+ copySomeData (myBuffer + start1, someData, size1);
+
+ if (size2 > 0)
+ copySomeData (myBuffer + start2, someData + size1, size2);
+
+ finishedWrite (size1 + size2);
+ }
+ @endcode
+
+ @param numToWrite indicates how many items you'd like to add to the buffer
+ @param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
+ @param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
+ @param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
+ the first block should be written
+ @param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
+ @see finishedWrite
+ */
+ void prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept;
+
+ /** Called after writing from the FIFO, to indicate that this many items have been added.
+ @see prepareToWrite
+ */
+ void finishedWrite (int numWritten) noexcept;
+
+ /** Returns the location within the buffer from which the next block of data should be read.
+
+ Because the section of data that you want to read from the buffer may overlap the end
+ and wrap around to the start, two blocks within your buffer are returned, and you
+ should read from both of them.
+
+ If the number of items you ask for is greater than the amount of data available, then
+ blockSize1 + blockSize2 may add up to a lower value than numWanted. If this happens, you
+ may decide to keep waiting and re-trying the method until there's enough data available.
+
+ After calling this method, if you choose to read the data, you must call finishedRead() to
+ tell the FIFO how much data you have consumed.
+
+ e.g.
+ @code
+ void readFromFifo (int* someData, int numItems)
+ {
+ int start1, size1, start2, size2;
+ prepareToRead (numSamples, start1, size1, start2, size2);
+
+ if (size1 > 0)
+ copySomeData (someData, myBuffer + start1, size1);
+
+ if (size2 > 0)
+ copySomeData (someData + size1, myBuffer + start2, size2);
+
+ finishedRead (size1 + size2);
+ }
+ @endcode
+
+ @param numWanted indicates how many items you'd like to add to the buffer
+ @param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
+ @param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
+ @param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
+ the first block should be written
+ @param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
+ @see finishedRead
+ */
+ void prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept;
+
+ /** Called after reading from the FIFO, to indicate that this many items have now been consumed.
+ @see prepareToRead
+ */
+ void finishedRead (int numRead) noexcept;
+
+
+private:
+ //==============================================================================
+ int bufferSize;
+ Atomic <int> validStart, validEnd;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AbstractFifo)
+};
+
+
+#endif // JUCE_ABSTRACTFIFO_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Array.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Array.h
new file mode 100644
index 0000000..375576a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Array.h
@@ -0,0 +1,1113 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ARRAY_H_INCLUDED
+#define JUCE_ARRAY_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Holds a resizable array of primitive or copy-by-value objects.
+
+ Examples of arrays are: Array<int>, Array<Rectangle> or Array<MyClass*>
+
+ The Array class can be used to hold simple, non-polymorphic objects as well as primitive types - to
+ do so, the class must fulfil these requirements:
+ - it must have a copy constructor and assignment operator
+ - it must be able to be relocated in memory by a memcpy without this causing any problems - so
+ objects whose functionality relies on external pointers or references to themselves can not be used.
+
+ You can of course have an array of pointers to any kind of object, e.g. Array<MyClass*>, but if
+ you do this, the array doesn't take any ownership of the objects - see the OwnedArray class or the
+ ReferenceCountedArray class for more powerful ways of holding lists of objects.
+
+ For holding lists of strings, you can use Array\<String\>, but it's usually better to use the
+ specialised class StringArray, which provides more useful functions.
+
+ To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
+ TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
+
+ @see OwnedArray, ReferenceCountedArray, StringArray, CriticalSection
+*/
+template <typename ElementType,
+ typename TypeOfCriticalSectionToUse = DummyCriticalSection,
+ int minimumAllocatedSize = 0>
+class Array
+{
+private:
+ typedef PARAMETER_TYPE (ElementType) ParameterType;
+
+public:
+ //==============================================================================
+ /** Creates an empty array. */
+ Array() noexcept
+ : numUsed (0)
+ {
+ }
+
+ /** Creates a copy of another array.
+ @param other the array to copy
+ */
+ Array (const Array<ElementType, TypeOfCriticalSectionToUse>& other)
+ {
+ const ScopedLockType lock (other.getLock());
+ numUsed = other.numUsed;
+ data.setAllocatedSize (other.numUsed);
+
+ for (int i = 0; i < numUsed; ++i)
+ new (data.elements + i) ElementType (other.data.elements[i]);
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ Array (Array<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
+ : data (static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data)),
+ numUsed (other.numUsed)
+ {
+ other.numUsed = 0;
+ }
+ #endif
+
+ /** Initalises from a null-terminated C array of values.
+
+ @param values the array to copy from
+ */
+ template <typename TypeToCreateFrom>
+ explicit Array (const TypeToCreateFrom* values)
+ : numUsed (0)
+ {
+ while (*values != TypeToCreateFrom())
+ add (*values++);
+ }
+
+ /** Initalises from a C array of values.
+
+ @param values the array to copy from
+ @param numValues the number of values in the array
+ */
+ template <typename TypeToCreateFrom>
+ Array (const TypeToCreateFrom* values, int numValues)
+ : numUsed (numValues)
+ {
+ data.setAllocatedSize (numValues);
+
+ for (int i = 0; i < numValues; ++i)
+ new (data.elements + i) ElementType (values[i]);
+ }
+
+ /** Destructor. */
+ ~Array()
+ {
+ deleteAllElements();
+ }
+
+ /** Copies another array.
+ @param other the array to copy
+ */
+ Array& operator= (const Array& other)
+ {
+ if (this != &other)
+ {
+ Array<ElementType, TypeOfCriticalSectionToUse> otherCopy (other);
+ swapWith (otherCopy);
+ }
+
+ return *this;
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ Array& operator= (Array&& other) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ deleteAllElements();
+ data = static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data);
+ numUsed = other.numUsed;
+ other.numUsed = 0;
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Compares this array to another one.
+ Two arrays are considered equal if they both contain the same set of
+ elements, in the same order.
+ @param other the other array to compare with
+ */
+ template <class OtherArrayType>
+ bool operator== (const OtherArrayType& other) const
+ {
+ const ScopedLockType lock (getLock());
+ const typename OtherArrayType::ScopedLockType lock2 (other.getLock());
+
+ if (numUsed != other.numUsed)
+ return false;
+
+ for (int i = numUsed; --i >= 0;)
+ if (! (data.elements [i] == other.data.elements [i]))
+ return false;
+
+ return true;
+ }
+
+ /** Compares this array to another one.
+ Two arrays are considered equal if they both contain the same set of
+ elements, in the same order.
+ @param other the other array to compare with
+ */
+ template <class OtherArrayType>
+ bool operator!= (const OtherArrayType& other) const
+ {
+ return ! operator== (other);
+ }
+
+ //==============================================================================
+ /** Removes all elements from the array.
+ This will remove all the elements, and free any storage that the array is
+ using. To clear the array without freeing the storage, use the clearQuick()
+ method instead.
+
+ @see clearQuick
+ */
+ void clear()
+ {
+ const ScopedLockType lock (getLock());
+ deleteAllElements();
+ data.setAllocatedSize (0);
+ numUsed = 0;
+ }
+
+ /** Removes all elements from the array without freeing the array's allocated storage.
+ @see clear
+ */
+ void clearQuick()
+ {
+ const ScopedLockType lock (getLock());
+ deleteAllElements();
+ numUsed = 0;
+ }
+
+ //==============================================================================
+ /** Returns the current number of elements in the array.
+ */
+ inline int size() const noexcept
+ {
+ return numUsed;
+ }
+
+ /** Returns one of the elements in the array.
+ If the index passed in is beyond the range of valid elements, this
+ will return a default value.
+
+ If you're certain that the index will always be a valid element, you
+ can call getUnchecked() instead, which is faster.
+
+ @param index the index of the element being requested (0 is the first element in the array)
+ @see getUnchecked, getFirst, getLast
+ */
+ ElementType operator[] (const int index) const
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (index, numUsed))
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ return ElementType();
+ }
+
+ /** Returns one of the elements in the array, without checking the index passed in.
+
+ Unlike the operator[] method, this will try to return an element without
+ checking that the index is within the bounds of the array, so should only
+ be used when you're confident that it will always be a valid index.
+
+ @param index the index of the element being requested (0 is the first element in the array)
+ @see operator[], getFirst, getLast
+ */
+ inline ElementType getUnchecked (const int index) const
+ {
+ const ScopedLockType lock (getLock());
+ jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ /** Returns a direct reference to one of the elements in the array, without checking the index passed in.
+
+ This is like getUnchecked, but returns a direct reference to the element, so that
+ you can alter it directly. Obviously this can be dangerous, so only use it when
+ absolutely necessary.
+
+ @param index the index of the element being requested (0 is the first element in the array)
+ @see operator[], getFirst, getLast
+ */
+ inline ElementType& getReference (const int index) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ /** Returns the first element in the array, or a default value if the array is empty.
+
+ @see operator[], getUnchecked, getLast
+ */
+ inline ElementType getFirst() const
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements[0];
+ }
+
+ return ElementType();
+ }
+
+ /** Returns the last element in the array, or a default value if the array is empty.
+
+ @see operator[], getUnchecked, getFirst
+ */
+ inline ElementType getLast() const
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements[numUsed - 1];
+ }
+
+ return ElementType();
+ }
+
+ /** Returns a pointer to the actual array data.
+ This pointer will only be valid until the next time a non-const method
+ is called on the array.
+ */
+ inline ElementType* getRawDataPointer() noexcept
+ {
+ return data.elements;
+ }
+
+ //==============================================================================
+ /** Returns a pointer to the first element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ElementType* begin() const noexcept
+ {
+ return data.elements;
+ }
+
+ /** Returns a pointer to the element which follows the last element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ElementType* end() const noexcept
+ {
+ #if JUCE_DEBUG
+ if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
+ return data.elements;
+ #endif
+
+ return data.elements + numUsed;
+ }
+
+ //==============================================================================
+ /** Finds the index of the first element which matches the value passed in.
+
+ This will search the array for the given object, and return the index
+ of its first occurrence. If the object isn't found, the method will return -1.
+
+ @param elementToLookFor the value or object to look for
+ @returns the index of the object, or -1 if it's not found
+ */
+ int indexOf (ParameterType elementToLookFor) const
+ {
+ const ScopedLockType lock (getLock());
+ const ElementType* e = data.elements.getData();
+ const ElementType* const end_ = e + numUsed;
+
+ for (; e != end_; ++e)
+ if (elementToLookFor == *e)
+ return static_cast <int> (e - data.elements.getData());
+
+ return -1;
+ }
+
+ /** Returns true if the array contains at least one occurrence of an object.
+
+ @param elementToLookFor the value or object to look for
+ @returns true if the item is found
+ */
+ bool contains (ParameterType elementToLookFor) const
+ {
+ const ScopedLockType lock (getLock());
+ const ElementType* e = data.elements.getData();
+ const ElementType* const end_ = e + numUsed;
+
+ for (; e != end_; ++e)
+ if (elementToLookFor == *e)
+ return true;
+
+ return false;
+ }
+
+ //==============================================================================
+ /** Appends a new element at the end of the array.
+
+ @param newElement the new object to add to the array
+ @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
+ */
+ void add (const ElementType& newElement)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + 1);
+ new (data.elements + numUsed++) ElementType (newElement);
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Appends a new element at the end of the array.
+
+ @param newElement the new object to add to the array
+ @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
+ */
+ void add (ElementType&& newElement)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + 1);
+ new (data.elements + numUsed++) ElementType (static_cast<ElementType&&> (newElement));
+ }
+ #endif
+
+ /** Inserts a new element into the array at a given position.
+
+ If the index is less than 0 or greater than the size of the array, the
+ element will be added to the end of the array.
+ Otherwise, it will be inserted into the array, moving all the later elements
+ along to make room.
+
+ @param indexToInsertAt the index at which the new element should be
+ inserted (pass in -1 to add it to the end)
+ @param newElement the new object to add to the array
+ @see add, addSorted, addUsingDefaultSort, set
+ */
+ void insert (int indexToInsertAt, ParameterType newElement)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+
+ if (isPositiveAndBelow (indexToInsertAt, numUsed))
+ {
+ ElementType* const insertPos = data.elements + indexToInsertAt;
+ const int numberToMove = numUsed - indexToInsertAt;
+
+ if (numberToMove > 0)
+ memmove (insertPos + 1, insertPos, ((size_t) numberToMove) * sizeof (ElementType));
+
+ new (insertPos) ElementType (newElement);
+ ++numUsed;
+ }
+ else
+ {
+ new (data.elements + numUsed++) ElementType (newElement);
+ }
+ }
+
+ /** Inserts multiple copies of an element into the array at a given position.
+
+ If the index is less than 0 or greater than the size of the array, the
+ element will be added to the end of the array.
+ Otherwise, it will be inserted into the array, moving all the later elements
+ along to make room.
+
+ @param indexToInsertAt the index at which the new element should be inserted
+ @param newElement the new object to add to the array
+ @param numberOfTimesToInsertIt how many copies of the value to insert
+ @see insert, add, addSorted, set
+ */
+ void insertMultiple (int indexToInsertAt, ParameterType newElement,
+ int numberOfTimesToInsertIt)
+ {
+ if (numberOfTimesToInsertIt > 0)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt);
+ ElementType* insertPos;
+
+ if (isPositiveAndBelow (indexToInsertAt, numUsed))
+ {
+ insertPos = data.elements + indexToInsertAt;
+ const int numberToMove = numUsed - indexToInsertAt;
+ memmove (insertPos + numberOfTimesToInsertIt, insertPos, ((size_t) numberToMove) * sizeof (ElementType));
+ }
+ else
+ {
+ insertPos = data.elements + numUsed;
+ }
+
+ numUsed += numberOfTimesToInsertIt;
+
+ while (--numberOfTimesToInsertIt >= 0)
+ new (insertPos++) ElementType (newElement);
+ }
+ }
+
+ /** Inserts an array of values into this array at a given position.
+
+ If the index is less than 0 or greater than the size of the array, the
+ new elements will be added to the end of the array.
+ Otherwise, they will be inserted into the array, moving all the later elements
+ along to make room.
+
+ @param indexToInsertAt the index at which the first new element should be inserted
+ @param newElements the new values to add to the array
+ @param numberOfElements how many items are in the array
+ @see insert, add, addSorted, set
+ */
+ void insertArray (int indexToInsertAt,
+ const ElementType* newElements,
+ int numberOfElements)
+ {
+ if (numberOfElements > 0)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + numberOfElements);
+ ElementType* insertPos = data.elements;
+
+ if (isPositiveAndBelow (indexToInsertAt, numUsed))
+ {
+ insertPos += indexToInsertAt;
+ const int numberToMove = numUsed - indexToInsertAt;
+ memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ElementType));
+ }
+ else
+ {
+ insertPos += numUsed;
+ }
+
+ numUsed += numberOfElements;
+
+ while (--numberOfElements >= 0)
+ new (insertPos++) ElementType (*newElements++);
+ }
+ }
+
+ /** Appends a new element at the end of the array as long as the array doesn't
+ already contain it.
+
+ If the array already contains an element that matches the one passed in, nothing
+ will be done.
+
+ @param newElement the new object to add to the array
+ */
+ void addIfNotAlreadyThere (ParameterType newElement)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (! contains (newElement))
+ add (newElement);
+ }
+
+ /** Replaces an element with a new value.
+
+ If the index is less than zero, this method does nothing.
+ If the index is beyond the end of the array, the item is added to the end of the array.
+
+ @param indexToChange the index whose value you want to change
+ @param newValue the new value to set for this index.
+ @see add, insert
+ */
+ void set (const int indexToChange, ParameterType newValue)
+ {
+ jassert (indexToChange >= 0);
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToChange, numUsed))
+ {
+ jassert (data.elements != nullptr);
+ data.elements [indexToChange] = newValue;
+ }
+ else if (indexToChange >= 0)
+ {
+ data.ensureAllocatedSize (numUsed + 1);
+ new (data.elements + numUsed++) ElementType (newValue);
+ }
+ }
+
+ /** Replaces an element with a new value without doing any bounds-checking.
+
+ This just sets a value directly in the array's internal storage, so you'd
+ better make sure it's in range!
+
+ @param indexToChange the index whose value you want to change
+ @param newValue the new value to set for this index.
+ @see set, getUnchecked
+ */
+ void setUnchecked (const int indexToChange, ParameterType newValue)
+ {
+ const ScopedLockType lock (getLock());
+ jassert (isPositiveAndBelow (indexToChange, numUsed));
+ data.elements [indexToChange] = newValue;
+ }
+
+ /** Adds elements from an array to the end of this array.
+
+ @param elementsToAdd an array of some kind of object from which elements
+ can be constructed.
+ @param numElementsToAdd how many elements are in this other array
+ @see add
+ */
+ template <typename Type>
+ void addArray (const Type* elementsToAdd, int numElementsToAdd)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numElementsToAdd > 0)
+ {
+ data.ensureAllocatedSize (numUsed + numElementsToAdd);
+
+ while (--numElementsToAdd >= 0)
+ {
+ new (data.elements + numUsed) ElementType (*elementsToAdd++);
+ ++numUsed;
+ }
+ }
+ }
+
+ /** Adds elements from a null-terminated array of pointers to the end of this array.
+
+ @param elementsToAdd an array of pointers to some kind of object from which elements
+ can be constructed. This array must be terminated by a nullptr
+ @see addArray
+ */
+ template <typename Type>
+ void addNullTerminatedArray (const Type* const* elementsToAdd)
+ {
+ int num = 0;
+ for (const Type* const* e = elementsToAdd; *e != nullptr; ++e)
+ ++num;
+
+ addArray (elementsToAdd, num);
+ }
+
+ /** This swaps the contents of this array with those of another array.
+
+ If you need to exchange two arrays, this is vastly quicker than using copy-by-value
+ because it just swaps their internal pointers.
+ */
+ template <class OtherArrayType>
+ void swapWith (OtherArrayType& otherArray) noexcept
+ {
+ const ScopedLockType lock1 (getLock());
+ const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
+ data.swapWith (otherArray.data);
+ std::swap (numUsed, otherArray.numUsed);
+ }
+
+ /** Adds elements from another array to the end of this array.
+
+ @param arrayToAddFrom the array from which to copy the elements
+ @param startIndex the first element of the other array to start copying from
+ @param numElementsToAdd how many elements to add from the other array. If this
+ value is negative or greater than the number of available elements,
+ all available elements will be copied.
+ @see add
+ */
+ template <class OtherArrayType>
+ void addArray (const OtherArrayType& arrayToAddFrom,
+ int startIndex = 0,
+ int numElementsToAdd = -1)
+ {
+ const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
+
+ {
+ const ScopedLockType lock2 (getLock());
+
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
+ numElementsToAdd = arrayToAddFrom.size() - startIndex;
+
+ while (--numElementsToAdd >= 0)
+ add (arrayToAddFrom.getUnchecked (startIndex++));
+ }
+ }
+
+ /** This will enlarge or shrink the array to the given number of elements, by adding
+ or removing items from its end.
+
+ If the array is smaller than the given target size, empty elements will be appended
+ until its size is as specified. If its size is larger than the target, items will be
+ removed from its end to shorten it.
+ */
+ void resize (const int targetNumItems)
+ {
+ jassert (targetNumItems >= 0);
+
+ const int numToAdd = targetNumItems - numUsed;
+ if (numToAdd > 0)
+ insertMultiple (numUsed, ElementType(), numToAdd);
+ else if (numToAdd < 0)
+ removeRange (targetNumItems, -numToAdd);
+ }
+
+ /** Inserts a new element into the array, assuming that the array is sorted.
+
+ This will use a comparator to find the position at which the new element
+ should go. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator to use to compare the elements - see the sort()
+ method for details about the form this object should take
+ @param newElement the new element to insert to the array
+ @returns the index at which the new item was added
+ @see addUsingDefaultSort, add, sort
+ */
+ template <class ElementComparator>
+ int addSorted (ElementComparator& comparator, ParameterType newElement)
+ {
+ const ScopedLockType lock (getLock());
+ const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newElement, 0, numUsed);
+ insert (index, newElement);
+ return index;
+ }
+
+ /** Inserts a new element into the array, assuming that the array is sorted.
+
+ This will use the DefaultElementComparator class for sorting, so your ElementType
+ must be suitable for use with that class. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param newElement the new element to insert to the array
+ @see addSorted, sort
+ */
+ void addUsingDefaultSort (ParameterType newElement)
+ {
+ DefaultElementComparator <ElementType> comparator;
+ addSorted (comparator, newElement);
+ }
+
+ /** Finds the index of an element in the array, assuming that the array is sorted.
+
+ This will use a comparator to do a binary-chop to find the index of the given
+ element, if it exists. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator to use to compare the elements - see the sort()
+ method for details about the form this object should take
+ @param elementToLookFor the element to search for
+ @returns the index of the element, or -1 if it's not found
+ @see addSorted, sort
+ */
+ template <typename ElementComparator, typename TargetValueType>
+ int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const
+ {
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+
+ const ScopedLockType lock (getLock());
+
+ for (int s = 0, e = numUsed;;)
+ {
+ if (s >= e)
+ return -1;
+
+ if (comparator.compareElements (elementToLookFor, data.elements [s]) == 0)
+ return s;
+
+ const int halfway = (s + e) / 2;
+ if (halfway == s)
+ return -1;
+
+ if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0)
+ s = halfway;
+ else
+ e = halfway;
+ }
+ }
+
+ //==============================================================================
+ /** Removes an element from the array.
+
+ This will remove the element at a given index, and move back
+ all the subsequent elements to close the gap.
+ If the index passed in is out-of-range, nothing will happen.
+
+ @param indexToRemove the index of the element to remove
+ @returns the element that has been removed
+ @see removeFirstMatchingValue, removeAllInstancesOf, removeRange
+ */
+ ElementType remove (const int indexToRemove)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToRemove, numUsed))
+ {
+ jassert (data.elements != nullptr);
+ ElementType removed (data.elements[indexToRemove]);
+ removeInternal (indexToRemove);
+ return removed;
+ }
+
+ return ElementType();
+ }
+
+ /** Removes an item from the array.
+
+ This will remove the first occurrence of the given element from the array.
+ If the item isn't found, no action is taken.
+
+ @param valueToRemove the object to try to remove
+ @see remove, removeRange
+ */
+ void removeFirstMatchingValue (ParameterType valueToRemove)
+ {
+ const ScopedLockType lock (getLock());
+ ElementType* const e = data.elements;
+
+ for (int i = 0; i < numUsed; ++i)
+ {
+ if (valueToRemove == e[i])
+ {
+ removeInternal (i);
+ break;
+ }
+ }
+ }
+
+ /** Removes an item from the array.
+
+ This will remove the first occurrence of the given element from the array.
+ If the item isn't found, no action is taken.
+
+ @param valueToRemove the object to try to remove
+ @see remove, removeRange
+ */
+ void removeAllInstancesOf (ParameterType valueToRemove)
+ {
+ const ScopedLockType lock (getLock());
+
+ for (int i = numUsed; --i >= 0;)
+ if (valueToRemove == data.elements[i])
+ removeInternal (i);
+ }
+
+ /** Removes a range of elements from the array.
+
+ This will remove a set of elements, starting from the given index,
+ and move subsequent elements down to close the gap.
+
+ If the range extends beyond the bounds of the array, it will
+ be safely clipped to the size of the array.
+
+ @param startIndex the index of the first element to remove
+ @param numberToRemove how many elements should be removed
+ @see remove, removeFirstMatchingValue, removeAllInstancesOf
+ */
+ void removeRange (int startIndex, int numberToRemove)
+ {
+ const ScopedLockType lock (getLock());
+ const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
+ startIndex = jlimit (0, numUsed, startIndex);
+
+ if (endIndex > startIndex)
+ {
+ ElementType* const e = data.elements + startIndex;
+
+ numberToRemove = endIndex - startIndex;
+ for (int i = 0; i < numberToRemove; ++i)
+ e[i].~ElementType();
+
+ const int numToShift = numUsed - endIndex;
+ if (numToShift > 0)
+ memmove (e, e + numberToRemove, ((size_t) numToShift) * sizeof (ElementType));
+
+ numUsed -= numberToRemove;
+ minimiseStorageAfterRemoval();
+ }
+ }
+
+ /** Removes the last n elements from the array.
+
+ @param howManyToRemove how many elements to remove from the end of the array
+ @see remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
+ */
+ void removeLast (int howManyToRemove = 1)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (howManyToRemove > numUsed)
+ howManyToRemove = numUsed;
+
+ for (int i = 1; i <= howManyToRemove; ++i)
+ data.elements [numUsed - i].~ElementType();
+
+ numUsed -= howManyToRemove;
+ minimiseStorageAfterRemoval();
+ }
+
+ /** Removes any elements which are also in another array.
+
+ @param otherArray the other array in which to look for elements to remove
+ @see removeValuesNotIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
+ */
+ template <class OtherArrayType>
+ void removeValuesIn (const OtherArrayType& otherArray)
+ {
+ const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (this == &otherArray)
+ {
+ clear();
+ }
+ else
+ {
+ if (otherArray.size() > 0)
+ {
+ for (int i = numUsed; --i >= 0;)
+ if (otherArray.contains (data.elements [i]))
+ removeInternal (i);
+ }
+ }
+ }
+
+ /** Removes any elements which are not found in another array.
+
+ Only elements which occur in this other array will be retained.
+
+ @param otherArray the array in which to look for elements NOT to remove
+ @see removeValuesIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
+ */
+ template <class OtherArrayType>
+ void removeValuesNotIn (const OtherArrayType& otherArray)
+ {
+ const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (this != &otherArray)
+ {
+ if (otherArray.size() <= 0)
+ {
+ clear();
+ }
+ else
+ {
+ for (int i = numUsed; --i >= 0;)
+ if (! otherArray.contains (data.elements [i]))
+ removeInternal (i);
+ }
+ }
+ }
+
+ /** Swaps over two elements in the array.
+
+ This swaps over the elements found at the two indexes passed in.
+ If either index is out-of-range, this method will do nothing.
+
+ @param index1 index of one of the elements to swap
+ @param index2 index of the other element to swap
+ */
+ void swap (const int index1,
+ const int index2)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (index1, numUsed)
+ && isPositiveAndBelow (index2, numUsed))
+ {
+ std::swap (data.elements [index1],
+ data.elements [index2]);
+ }
+ }
+
+ /** Moves one of the values to a different position.
+
+ This will move the value to a specified index, shuffling along
+ any intervening elements as required.
+
+ So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
+ move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
+
+ @param currentIndex the index of the value to be moved. If this isn't a
+ valid index, then nothing will be done
+ @param newIndex the index at which you'd like this value to end up. If this
+ is less than zero, the value will be moved to the end
+ of the array
+ */
+ void move (const int currentIndex, int newIndex) noexcept
+ {
+ if (currentIndex != newIndex)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (currentIndex, numUsed))
+ {
+ if (! isPositiveAndBelow (newIndex, numUsed))
+ newIndex = numUsed - 1;
+
+ char tempCopy [sizeof (ElementType)];
+ memcpy (tempCopy, data.elements + currentIndex, sizeof (ElementType));
+
+ if (newIndex > currentIndex)
+ {
+ memmove (data.elements + currentIndex,
+ data.elements + currentIndex + 1,
+ sizeof (ElementType) * (size_t) (newIndex - currentIndex));
+ }
+ else
+ {
+ memmove (data.elements + newIndex + 1,
+ data.elements + newIndex,
+ sizeof (ElementType) * (size_t) (currentIndex - newIndex));
+ }
+
+ memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType));
+ }
+ }
+ }
+
+ //==============================================================================
+ /** Reduces the amount of storage being used by the array.
+
+ Arrays typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads()
+ {
+ const ScopedLockType lock (getLock());
+ data.shrinkToNoMoreThan (numUsed);
+ }
+
+ /** Increases the array's internal storage to hold a minimum number of elements.
+
+ Calling this before adding a large known number of elements means that
+ the array won't have to keep dynamically resizing itself as the elements
+ are added, and it'll therefore be more efficient.
+ */
+ void ensureStorageAllocated (const int minNumElements)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (minNumElements);
+ }
+
+ //==============================================================================
+ /** Sorts the elements in the array.
+
+ This will use a comparator object to sort the elements into order. The object
+ passed must have a method of the form:
+ @code
+ int compareElements (ElementType first, ElementType second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator the comparator to use for comparing elements.
+ @param retainOrderOfEquivalentItems if this is true, then items
+ which the comparator says are equivalent will be
+ kept in the order in which they currently appear
+ in the array. This is slower to perform, but may
+ be important in some cases. If it's false, a faster
+ algorithm is used, but equivalent elements may be
+ rearranged.
+
+ @see addSorted, indexOfSorted, sortArray
+ */
+ template <class ElementComparator>
+ void sort (ElementComparator& comparator,
+ const bool retainOrderOfEquivalentItems = false) const
+ {
+ const ScopedLockType lock (getLock());
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+ sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
+ }
+
+ //==============================================================================
+ /** Returns the CriticalSection that locks this array.
+ To lock, you can call getLock().enter() and getLock().exit(), or preferably use
+ an object of ScopedLockType as an RAII lock for it.
+ */
+ inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; }
+
+ /** Returns the type of scoped lock to use for locking this array */
+ typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
+
+
+ //==============================================================================
+ #ifndef DOXYGEN
+ // Note that the swapWithArray method has been replaced by a more flexible templated version,
+ // and renamed "swapWith" to be more consistent with the names used in other classes.
+ JUCE_DEPRECATED_WITH_BODY (void swapWithArray (Array& other) noexcept, { swapWith (other); })
+ #endif
+
+private:
+ //==============================================================================
+ ArrayAllocationBase <ElementType, TypeOfCriticalSectionToUse> data;
+ int numUsed;
+
+ void removeInternal (const int indexToRemove)
+ {
+ --numUsed;
+ ElementType* const e = data.elements + indexToRemove;
+ e->~ElementType();
+ const int numberToShift = numUsed - indexToRemove;
+
+ if (numberToShift > 0)
+ memmove (e, e + 1, ((size_t) numberToShift) * sizeof (ElementType));
+
+ minimiseStorageAfterRemoval();
+ }
+
+ inline void deleteAllElements() noexcept
+ {
+ for (int i = 0; i < numUsed; ++i)
+ data.elements[i].~ElementType();
+ }
+
+ void minimiseStorageAfterRemoval()
+ {
+ if (data.numAllocated > jmax (minimumAllocatedSize, numUsed * 2))
+ data.shrinkToNoMoreThan (jmax (numUsed, jmax (minimumAllocatedSize, 64 / (int) sizeof (ElementType))));
+ }
+};
+
+
+#endif // JUCE_ARRAY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ArrayAllocationBase.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ArrayAllocationBase.h
new file mode 100644
index 0000000..cfbe464
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ArrayAllocationBase.h
@@ -0,0 +1,138 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ARRAYALLOCATIONBASE_H_INCLUDED
+#define JUCE_ARRAYALLOCATIONBASE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Implements some basic array storage allocation functions.
+
+ This class isn't really for public use - it's used by the other
+ array classes, but might come in handy for some purposes.
+
+ It inherits from a critical section class to allow the arrays to use
+ the "empty base class optimisation" pattern to reduce their footprint.
+
+ @see Array, OwnedArray, ReferenceCountedArray
+*/
+template <class ElementType, class TypeOfCriticalSectionToUse>
+class ArrayAllocationBase : public TypeOfCriticalSectionToUse
+{
+public:
+ //==============================================================================
+ /** Creates an empty array. */
+ ArrayAllocationBase() noexcept
+ : numAllocated (0)
+ {
+ }
+
+ /** Destructor. */
+ ~ArrayAllocationBase() noexcept
+ {
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ ArrayAllocationBase (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
+ : elements (static_cast <HeapBlock <ElementType>&&> (other.elements)),
+ numAllocated (other.numAllocated)
+ {
+ }
+
+ ArrayAllocationBase& operator= (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
+ {
+ elements = static_cast <HeapBlock <ElementType>&&> (other.elements);
+ numAllocated = other.numAllocated;
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Changes the amount of storage allocated.
+
+ This will retain any data currently held in the array, and either add or
+ remove extra space at the end.
+
+ @param numElements the number of elements that are needed
+ */
+ void setAllocatedSize (const int numElements)
+ {
+ if (numAllocated != numElements)
+ {
+ if (numElements > 0)
+ elements.realloc ((size_t) numElements);
+ else
+ elements.free();
+
+ numAllocated = numElements;
+ }
+ }
+
+ /** Increases the amount of storage allocated if it is less than a given amount.
+
+ This will retain any data currently held in the array, but will add
+ extra space at the end to make sure there it's at least as big as the size
+ passed in. If it's already bigger, no action is taken.
+
+ @param minNumElements the minimum number of elements that are needed
+ */
+ void ensureAllocatedSize (const int minNumElements)
+ {
+ if (minNumElements > numAllocated)
+ setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
+
+ jassert (numAllocated <= 0 || elements != nullptr);
+ }
+
+ /** Minimises the amount of storage allocated so that it's no more than
+ the given number of elements.
+ */
+ void shrinkToNoMoreThan (const int maxNumElements)
+ {
+ if (maxNumElements < numAllocated)
+ setAllocatedSize (maxNumElements);
+ }
+
+ /** Swap the contents of two objects. */
+ void swapWith (ArrayAllocationBase <ElementType, TypeOfCriticalSectionToUse>& other) noexcept
+ {
+ elements.swapWith (other.elements);
+ std::swap (numAllocated, other.numAllocated);
+ }
+
+ //==============================================================================
+ HeapBlock <ElementType> elements;
+ int numAllocated;
+
+private:
+ JUCE_DECLARE_NON_COPYABLE (ArrayAllocationBase)
+};
+
+
+#endif // JUCE_ARRAYALLOCATIONBASE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.cpp
new file mode 100644
index 0000000..38f5c5f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.cpp
@@ -0,0 +1,133 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+DynamicObject::DynamicObject()
+{
+}
+
+DynamicObject::DynamicObject (const DynamicObject& other)
+ : ReferenceCountedObject(), properties (other.properties)
+{
+}
+
+DynamicObject::~DynamicObject()
+{
+}
+
+bool DynamicObject::hasProperty (const Identifier& propertyName) const
+{
+ const var* const v = properties.getVarPointer (propertyName);
+ return v != nullptr && ! v->isMethod();
+}
+
+var DynamicObject::getProperty (const Identifier& propertyName) const
+{
+ return properties [propertyName];
+}
+
+void DynamicObject::setProperty (const Identifier& propertyName, const var& newValue)
+{
+ properties.set (propertyName, newValue);
+}
+
+void DynamicObject::removeProperty (const Identifier& propertyName)
+{
+ properties.remove (propertyName);
+}
+
+bool DynamicObject::hasMethod (const Identifier& methodName) const
+{
+ return getProperty (methodName).isMethod();
+}
+
+var DynamicObject::invokeMethod (Identifier method, const var::NativeFunctionArgs& args)
+{
+ if (var::NativeFunction function = properties [method].getNativeFunction())
+ return function (args);
+
+ return var();
+}
+
+void DynamicObject::setMethod (Identifier name, var::NativeFunction function)
+{
+ properties.set (name, var (function));
+}
+
+void DynamicObject::clear()
+{
+ properties.clear();
+}
+
+void DynamicObject::cloneAllProperties()
+{
+ for (int i = properties.size(); --i >= 0;)
+ if (var* v = properties.getVarPointerAt (i))
+ *v = v->clone();
+}
+
+DynamicObject::Ptr DynamicObject::clone()
+{
+ Ptr d (new DynamicObject (*this));
+ d->cloneAllProperties();
+ return d;
+}
+
+void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine)
+{
+ out << '{';
+ if (! allOnOneLine)
+ out << newLine;
+
+ const int numValues = properties.size();
+
+ for (int i = 0; i < numValues; ++i)
+ {
+ if (! allOnOneLine)
+ JSONFormatter::writeSpaces (out, indentLevel + JSONFormatter::indentSize);
+
+ out << '"';
+ JSONFormatter::writeString (out, properties.getName (i));
+ out << "\": ";
+ JSONFormatter::write (out, properties.getValueAt (i), indentLevel + JSONFormatter::indentSize, allOnOneLine);
+
+ if (i < numValues - 1)
+ {
+ if (allOnOneLine)
+ out << ", ";
+ else
+ out << ',' << newLine;
+ }
+ else if (! allOnOneLine)
+ out << newLine;
+ }
+
+ if (! allOnOneLine)
+ JSONFormatter::writeSpaces (out, indentLevel);
+
+ out << '}';
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.h
new file mode 100644
index 0000000..5c624a4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_DynamicObject.h
@@ -0,0 +1,139 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_DYNAMICOBJECT_H_INCLUDED
+#define JUCE_DYNAMICOBJECT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a dynamically implemented object.
+
+ This class is primarily intended for wrapping scripting language objects,
+ but could be used for other purposes.
+
+ An instance of a DynamicObject can be used to store named properties, and
+ by subclassing hasMethod() and invokeMethod(), you can give your object
+ methods.
+*/
+class JUCE_API DynamicObject : public ReferenceCountedObject
+{
+public:
+ //==============================================================================
+ DynamicObject();
+ DynamicObject (const DynamicObject&);
+ ~DynamicObject();
+
+ typedef ReferenceCountedObjectPtr<DynamicObject> Ptr;
+
+ //==============================================================================
+ /** Returns true if the object has a property with this name.
+ Note that if the property is actually a method, this will return false.
+ */
+ virtual bool hasProperty (const Identifier& propertyName) const;
+
+ /** Returns a named property.
+ This returns var::null if no such property exists.
+ */
+ virtual var getProperty (const Identifier& propertyName) const;
+
+ /** Sets a named property. */
+ virtual void setProperty (const Identifier& propertyName, const var& newValue);
+
+ /** Removes a named property. */
+ virtual void removeProperty (const Identifier& propertyName);
+
+ //==============================================================================
+ /** Checks whether this object has the specified method.
+
+ The default implementation of this just checks whether there's a property
+ with this name that's actually a method, but this can be overridden for
+ building objects with dynamic invocation.
+ */
+ virtual bool hasMethod (const Identifier& methodName) const;
+
+ /** Invokes a named method on this object.
+
+ The default implementation looks up the named property, and if it's a method
+ call, then it invokes it.
+
+ This method is virtual to allow more dynamic invocation to used for objects
+ where the methods may not already be set as properies.
+ */
+ virtual var invokeMethod (Identifier methodName,
+ const var::NativeFunctionArgs& args);
+
+ /** Adds a method to the class.
+
+ This is basically the same as calling setProperty (methodName, (var::NativeFunction) myFunction), but
+ helps to avoid accidentally invoking the wrong type of var constructor. It also makes
+ the code easier to read,
+ */
+ void setMethod (Identifier methodName, var::NativeFunction function);
+
+ //==============================================================================
+ /** Removes all properties and methods from the object. */
+ void clear();
+
+ /** Returns the NamedValueSet that holds the object's properties. */
+ NamedValueSet& getProperties() noexcept { return properties; }
+
+ /** Calls var::clone() on all the properties that this object contains. */
+ void cloneAllProperties();
+
+ //==============================================================================
+ /** Returns a clone of this object.
+ The default implementation of this method just returns a new DynamicObject
+ with a (deep) copy of all of its properties. Subclasses can override this to
+ implement their own custom copy routines.
+ */
+ virtual Ptr clone();
+
+ //==============================================================================
+ /** Writes this object to a text stream in JSON format.
+ This method is used by JSON::toString and JSON::writeToStream, and you should
+ never need to call it directly, but it's virtual so that custom object types
+ can stringify themselves appropriately.
+ */
+ virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine);
+
+private:
+ //==============================================================================
+ NamedValueSet properties;
+
+ #if JUCE_CATCH_DEPRECATED_CODE_MISUSE
+ // These methods have been deprecated - use var::invoke instead
+ virtual void invokeMethod (const Identifier&, const var*, int) {}
+ #endif
+
+ JUCE_LEAK_DETECTOR (DynamicObject)
+};
+
+
+
+#endif // JUCE_DYNAMICOBJECT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ElementComparator.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ElementComparator.h
new file mode 100644
index 0000000..01dc5b7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ElementComparator.h
@@ -0,0 +1,195 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ELEMENTCOMPARATOR_H_INCLUDED
+#define JUCE_ELEMENTCOMPARATOR_H_INCLUDED
+
+#ifndef DOXYGEN
+
+/** This is an internal helper class which converts a juce ElementComparator style
+ class (using a "compareElements" method) into a class that's compatible with
+ std::sort (i.e. using an operator() to compare the elements)
+*/
+template <typename ElementComparator>
+struct SortFunctionConverter
+{
+ SortFunctionConverter (ElementComparator& e) : comparator (e) {}
+
+ template <typename Type>
+ bool operator() (Type a, Type b) { return comparator.compareElements (a, b) < 0; }
+
+private:
+ ElementComparator& comparator;
+ SortFunctionConverter& operator= (const SortFunctionConverter&) JUCE_DELETED_FUNCTION;
+};
+
+#endif
+
+
+//==============================================================================
+/**
+ Sorts a range of elements in an array.
+
+ The comparator object that is passed-in must define a public method with the following
+ signature:
+ @code
+ int compareElements (ElementType first, ElementType second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator an object which defines a compareElements() method
+ @param array the array to sort
+ @param firstElement the index of the first element of the range to be sorted
+ @param lastElement the index of the last element in the range that needs
+ sorting (this is inclusive)
+ @param retainOrderOfEquivalentItems if true, the order of items that the
+ comparator deems the same will be maintained - this will be
+ a slower algorithm than if they are allowed to be moved around.
+
+ @see sortArrayRetainingOrder
+*/
+template <class ElementType, class ElementComparator>
+static void sortArray (ElementComparator& comparator,
+ ElementType* const array,
+ int firstElement,
+ int lastElement,
+ const bool retainOrderOfEquivalentItems)
+{
+ SortFunctionConverter<ElementComparator> converter (comparator);
+
+ if (retainOrderOfEquivalentItems)
+ std::stable_sort (array + firstElement, array + lastElement + 1, converter);
+ else
+ std::sort (array + firstElement, array + lastElement + 1, converter);
+}
+
+
+//==============================================================================
+/**
+ Searches a sorted array of elements, looking for the index at which a specified value
+ should be inserted for it to be in the correct order.
+
+ The comparator object that is passed-in must define a public method with the following
+ signature:
+ @code
+ int compareElements (ElementType first, ElementType second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator an object which defines a compareElements() method
+ @param array the array to search
+ @param newElement the value that is going to be inserted
+ @param firstElement the index of the first element to search
+ @param lastElement the index of the last element in the range (this is non-inclusive)
+*/
+template <class ElementType, class ElementComparator>
+static int findInsertIndexInSortedArray (ElementComparator& comparator,
+ ElementType* const array,
+ const ElementType newElement,
+ int firstElement,
+ int lastElement)
+{
+ jassert (firstElement <= lastElement);
+
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+
+ while (firstElement < lastElement)
+ {
+ if (comparator.compareElements (newElement, array [firstElement]) == 0)
+ {
+ ++firstElement;
+ break;
+ }
+ else
+ {
+ const int halfway = (firstElement + lastElement) >> 1;
+
+ if (halfway == firstElement)
+ {
+ if (comparator.compareElements (newElement, array [halfway]) >= 0)
+ ++firstElement;
+
+ break;
+ }
+ else if (comparator.compareElements (newElement, array [halfway]) >= 0)
+ {
+ firstElement = halfway;
+ }
+ else
+ {
+ lastElement = halfway;
+ }
+ }
+ }
+
+ return firstElement;
+}
+
+//==============================================================================
+/**
+ A simple ElementComparator class that can be used to sort an array of
+ objects that support the '<' operator.
+
+ This will work for primitive types and objects that implement operator<().
+
+ Example: @code
+ Array <int> myArray;
+ DefaultElementComparator<int> sorter;
+ myArray.sort (sorter);
+ @endcode
+
+ @see ElementComparator
+*/
+template <class ElementType>
+class DefaultElementComparator
+{
+private:
+ typedef PARAMETER_TYPE (ElementType) ParameterType;
+
+public:
+ static int compareElements (ParameterType first, ParameterType second)
+ {
+ return (first < second) ? -1 : ((second < first) ? 1 : 0);
+ }
+};
+
+
+#endif // JUCE_ELEMENTCOMPARATOR_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_HashMap.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_HashMap.h
new file mode 100644
index 0000000..07d02b4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_HashMap.h
@@ -0,0 +1,455 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_HASHMAP_H_INCLUDED
+#define JUCE_HASHMAP_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A simple class to generate hash functions for some primitive types, intended for
+ use with the HashMap class.
+ @see HashMap
+*/
+struct DefaultHashFunctions
+{
+ /** Generates a simple hash from an integer. */
+ int generateHash (const int key, const int upperLimit) const noexcept { return std::abs (key) % upperLimit; }
+ /** Generates a simple hash from an int64. */
+ int generateHash (const int64 key, const int upperLimit) const noexcept { return std::abs ((int) key) % upperLimit; }
+ /** Generates a simple hash from a string. */
+ int generateHash (const String& key, const int upperLimit) const noexcept { return (int) (((uint32) key.hashCode()) % (uint32) upperLimit); }
+ /** Generates a simple hash from a variant. */
+ int generateHash (const var& key, const int upperLimit) const noexcept { return generateHash (key.toString(), upperLimit); }
+};
+
+
+//==============================================================================
+/**
+ Holds a set of mappings between some key/value pairs.
+
+ The types of the key and value objects are set as template parameters.
+ You can also specify a class to supply a hash function that converts a key value
+ into an hashed integer. This class must have the form:
+
+ @code
+ struct MyHashGenerator
+ {
+ int generateHash (MyKeyType key, int upperLimit) const
+ {
+ // The function must return a value 0 <= x < upperLimit
+ return someFunctionOfMyKeyType (key) % upperLimit;
+ }
+ };
+ @endcode
+
+ Like the Array class, the key and value types are expected to be copy-by-value
+ types, so if you define them to be pointer types, this class won't delete the
+ objects that they point to.
+
+ If you don't supply a class for the HashFunctionType template parameter, the
+ default one provides some simple mappings for strings and ints.
+
+ @code
+ HashMap<int, String> hash;
+ hash.set (1, "item1");
+ hash.set (2, "item2");
+
+ DBG (hash [1]); // prints "item1"
+ DBG (hash [2]); // prints "item2"
+
+ // This iterates the map, printing all of its key -> value pairs..
+ for (HashMap<int, String>::Iterator i (hash); i.next();)
+ DBG (i.getKey() << " -> " << i.getValue());
+ @endcode
+
+ @tparam HashFunctionType The class of hash function, which must be copy-constructible.
+ @see CriticalSection, DefaultHashFunctions, NamedValueSet, SortedSet
+*/
+template <typename KeyType,
+ typename ValueType,
+ class HashFunctionType = DefaultHashFunctions,
+ class TypeOfCriticalSectionToUse = DummyCriticalSection>
+class HashMap
+{
+private:
+ typedef PARAMETER_TYPE (KeyType) KeyTypeParameter;
+ typedef PARAMETER_TYPE (ValueType) ValueTypeParameter;
+
+public:
+ //==============================================================================
+ /** Creates an empty hash-map.
+
+ @param numberOfSlots Specifies the number of hash entries the map will use. This will be
+ the "upperLimit" parameter that is passed to your generateHash()
+ function. The number of hash slots will grow automatically if necessary,
+ or it can be remapped manually using remapTable().
+ @param hashFunction An instance of HashFunctionType, which will be copied and
+ stored to use with the HashMap. This parameter can be omitted
+ if HashFunctionType has a default constructor.
+ */
+ explicit HashMap (int numberOfSlots = defaultHashTableSize,
+ HashFunctionType hashFunction = HashFunctionType())
+ : hashFunctionToUse (hashFunction), totalNumItems (0)
+ {
+ hashSlots.insertMultiple (0, nullptr, numberOfSlots);
+ }
+
+ /** Destructor. */
+ ~HashMap()
+ {
+ clear();
+ }
+
+ //==============================================================================
+ /** Removes all values from the map.
+ Note that this will clear the content, but won't affect the number of slots (see
+ remapTable and getNumSlots).
+ */
+ void clear()
+ {
+ const ScopedLockType sl (getLock());
+
+ for (int i = hashSlots.size(); --i >= 0;)
+ {
+ HashEntry* h = hashSlots.getUnchecked(i);
+
+ while (h != nullptr)
+ {
+ const ScopedPointer<HashEntry> deleter (h);
+ h = h->nextEntry;
+ }
+
+ hashSlots.set (i, nullptr);
+ }
+
+ totalNumItems = 0;
+ }
+
+ //==============================================================================
+ /** Returns the current number of items in the map. */
+ inline int size() const noexcept
+ {
+ return totalNumItems;
+ }
+
+ /** Returns the value corresponding to a given key.
+ If the map doesn't contain the key, a default instance of the value type is returned.
+ @param keyToLookFor the key of the item being requested
+ */
+ inline ValueType operator[] (KeyTypeParameter keyToLookFor) const
+ {
+ const ScopedLockType sl (getLock());
+
+ for (const HashEntry* entry = hashSlots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
+ if (entry->key == keyToLookFor)
+ return entry->value;
+
+ return ValueType();
+ }
+
+ //==============================================================================
+ /** Returns true if the map contains an item with the specied key. */
+ bool contains (KeyTypeParameter keyToLookFor) const
+ {
+ const ScopedLockType sl (getLock());
+
+ for (const HashEntry* entry = hashSlots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
+ if (entry->key == keyToLookFor)
+ return true;
+
+ return false;
+ }
+
+ /** Returns true if the hash contains at least one occurrence of a given value. */
+ bool containsValue (ValueTypeParameter valueToLookFor) const
+ {
+ const ScopedLockType sl (getLock());
+
+ for (int i = getNumSlots(); --i >= 0;)
+ for (const HashEntry* entry = hashSlots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
+ if (entry->value == valueToLookFor)
+ return true;
+
+ return false;
+ }
+
+ //==============================================================================
+ /** Adds or replaces an element in the hash-map.
+ If there's already an item with the given key, this will replace its value. Otherwise, a new item
+ will be added to the map.
+ */
+ void set (KeyTypeParameter newKey, ValueTypeParameter newValue)
+ {
+ const ScopedLockType sl (getLock());
+ const int hashIndex = generateHashFor (newKey);
+
+ HashEntry* const firstEntry = hashSlots.getUnchecked (hashIndex);
+
+ for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry)
+ {
+ if (entry->key == newKey)
+ {
+ entry->value = newValue;
+ return;
+ }
+ }
+
+ hashSlots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry));
+ ++totalNumItems;
+
+ if (totalNumItems > (getNumSlots() * 3) / 2)
+ remapTable (getNumSlots() * 2);
+ }
+
+ /** Removes an item with the given key. */
+ void remove (KeyTypeParameter keyToRemove)
+ {
+ const ScopedLockType sl (getLock());
+ const int hashIndex = generateHashFor (keyToRemove);
+ HashEntry* entry = hashSlots.getUnchecked (hashIndex);
+ HashEntry* previous = nullptr;
+
+ while (entry != nullptr)
+ {
+ if (entry->key == keyToRemove)
+ {
+ const ScopedPointer<HashEntry> deleter (entry);
+
+ entry = entry->nextEntry;
+
+ if (previous != nullptr)
+ previous->nextEntry = entry;
+ else
+ hashSlots.set (hashIndex, entry);
+
+ --totalNumItems;
+ }
+ else
+ {
+ previous = entry;
+ entry = entry->nextEntry;
+ }
+ }
+ }
+
+ /** Removes all items with the given value. */
+ void removeValue (ValueTypeParameter valueToRemove)
+ {
+ const ScopedLockType sl (getLock());
+
+ for (int i = getNumSlots(); --i >= 0;)
+ {
+ HashEntry* entry = hashSlots.getUnchecked(i);
+ HashEntry* previous = nullptr;
+
+ while (entry != nullptr)
+ {
+ if (entry->value == valueToRemove)
+ {
+ const ScopedPointer<HashEntry> deleter (entry);
+
+ entry = entry->nextEntry;
+
+ if (previous != nullptr)
+ previous->nextEntry = entry;
+ else
+ hashSlots.set (i, entry);
+
+ --totalNumItems;
+ }
+ else
+ {
+ previous = entry;
+ entry = entry->nextEntry;
+ }
+ }
+ }
+ }
+
+ /** Remaps the hash-map to use a different number of slots for its hash function.
+ Each slot corresponds to a single hash-code, and each one can contain multiple items.
+ @see getNumSlots()
+ */
+ void remapTable (int newNumberOfSlots)
+ {
+ HashMap newTable (newNumberOfSlots);
+
+ for (int i = getNumSlots(); --i >= 0;)
+ for (const HashEntry* entry = hashSlots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
+ newTable.set (entry->key, entry->value);
+
+ swapWith (newTable);
+ }
+
+ /** Returns the number of slots which are available for hashing.
+ Each slot corresponds to a single hash-code, and each one can contain multiple items.
+ @see getNumSlots()
+ */
+ inline int getNumSlots() const noexcept
+ {
+ return hashSlots.size();
+ }
+
+ //==============================================================================
+ /** Efficiently swaps the contents of two hash-maps. */
+ template <class OtherHashMapType>
+ void swapWith (OtherHashMapType& otherHashMap) noexcept
+ {
+ const ScopedLockType lock1 (getLock());
+ const typename OtherHashMapType::ScopedLockType lock2 (otherHashMap.getLock());
+
+ hashSlots.swapWith (otherHashMap.hashSlots);
+ std::swap (totalNumItems, otherHashMap.totalNumItems);
+ }
+
+ //==============================================================================
+ /** Returns the CriticalSection that locks this structure.
+ To lock, you can call getLock().enter() and getLock().exit(), or preferably use
+ an object of ScopedLockType as an RAII lock for it.
+ */
+ inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return lock; }
+
+ /** Returns the type of scoped lock to use for locking this array */
+ typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
+
+private:
+ //==============================================================================
+ class HashEntry
+ {
+ public:
+ HashEntry (KeyTypeParameter k, ValueTypeParameter val, HashEntry* const next)
+ : key (k), value (val), nextEntry (next)
+ {}
+
+ const KeyType key;
+ ValueType value;
+ HashEntry* nextEntry;
+
+ JUCE_DECLARE_NON_COPYABLE (HashEntry)
+ };
+
+public:
+ //==============================================================================
+ /** Iterates over the items in a HashMap.
+
+ To use it, repeatedly call next() until it returns false, e.g.
+ @code
+ HashMap <String, String> myMap;
+
+ HashMap<String, String>::Iterator i (myMap);
+
+ while (i.next())
+ {
+ DBG (i.getKey() << " -> " << i.getValue());
+ }
+ @endcode
+
+ The order in which items are iterated bears no resemblence to the order in which
+ they were originally added!
+
+ Obviously as soon as you call any non-const methods on the original hash-map, any
+ iterators that were created beforehand will cease to be valid, and should not be used.
+
+ @see HashMap
+ */
+ class Iterator
+ {
+ public:
+ //==============================================================================
+ Iterator (const HashMap& hashMapToIterate)
+ : hashMap (hashMapToIterate), entry (nullptr), index (0)
+ {}
+
+ /** Moves to the next item, if one is available.
+ When this returns true, you can get the item's key and value using getKey() and
+ getValue(). If it returns false, the iteration has finished and you should stop.
+ */
+ bool next()
+ {
+ if (entry != nullptr)
+ entry = entry->nextEntry;
+
+ while (entry == nullptr)
+ {
+ if (index >= hashMap.getNumSlots())
+ return false;
+
+ entry = hashMap.hashSlots.getUnchecked (index++);
+ }
+
+ return true;
+ }
+
+ /** Returns the current item's key.
+ This should only be called when a call to next() has just returned true.
+ */
+ KeyType getKey() const
+ {
+ return entry != nullptr ? entry->key : KeyType();
+ }
+
+ /** Returns the current item's value.
+ This should only be called when a call to next() has just returned true.
+ */
+ ValueType getValue() const
+ {
+ return entry != nullptr ? entry->value : ValueType();
+ }
+
+ private:
+ //==============================================================================
+ const HashMap& hashMap;
+ HashEntry* entry;
+ int index;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Iterator)
+ };
+
+private:
+ //==============================================================================
+ enum { defaultHashTableSize = 101 };
+ friend class Iterator;
+
+ HashFunctionType hashFunctionToUse;
+ Array<HashEntry*> hashSlots;
+ int totalNumItems;
+ TypeOfCriticalSectionToUse lock;
+
+ int generateHashFor (KeyTypeParameter key) const
+ {
+ const int hash = hashFunctionToUse.generateHash (key, getNumSlots());
+ jassert (isPositiveAndBelow (hash, getNumSlots())); // your hash function is generating out-of-range numbers!
+ return hash;
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HashMap)
+};
+
+
+#endif // JUCE_HASHMAP_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_LinkedListPointer.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_LinkedListPointer.h
new file mode 100644
index 0000000..a27e521
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_LinkedListPointer.h
@@ -0,0 +1,371 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_LINKEDLISTPOINTER_H_INCLUDED
+#define JUCE_LINKEDLISTPOINTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Helps to manipulate singly-linked lists of objects.
+
+ For objects that are designed to contain a pointer to the subsequent item in the
+ list, this class contains methods to deal with the list. To use it, the ObjectType
+ class that it points to must contain a LinkedListPointer called nextListItem, e.g.
+
+ @code
+ struct MyObject
+ {
+ int x, y, z;
+
+ // A linkable object must contain a member with this name and type, which must be
+ // accessible by the LinkedListPointer class. (This doesn't mean it has to be public -
+ // you could make your class a friend of a LinkedListPointer<MyObject> instead).
+ LinkedListPointer<MyObject> nextListItem;
+ };
+
+ LinkedListPointer<MyObject> myList;
+ myList.append (new MyObject());
+ myList.append (new MyObject());
+
+ int numItems = myList.size(); // returns 2
+ MyObject* lastInList = myList.getLast();
+ @endcode
+*/
+template <class ObjectType>
+class LinkedListPointer
+{
+public:
+ //==============================================================================
+ /** Creates a null pointer to an empty list. */
+ LinkedListPointer() noexcept
+ : item (nullptr)
+ {
+ }
+
+ /** Creates a pointer to a list whose head is the item provided. */
+ explicit LinkedListPointer (ObjectType* const headItem) noexcept
+ : item (headItem)
+ {
+ }
+
+ /** Sets this pointer to point to a new list. */
+ LinkedListPointer& operator= (ObjectType* const newItem) noexcept
+ {
+ item = newItem;
+ return *this;
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ LinkedListPointer (LinkedListPointer&& other) noexcept
+ : item (other.item)
+ {
+ other.item = nullptr;
+ }
+
+ LinkedListPointer& operator= (LinkedListPointer&& other) noexcept
+ {
+ jassert (this != &other); // hopefully the compiler should make this situation impossible!
+
+ item = other.item;
+ other.item = nullptr;
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Returns the item which this pointer points to. */
+ inline operator ObjectType*() const noexcept
+ {
+ return item;
+ }
+
+ /** Returns the item which this pointer points to. */
+ inline ObjectType* get() const noexcept
+ {
+ return item;
+ }
+
+ /** Returns the last item in the list which this pointer points to.
+ This will iterate the list and return the last item found. Obviously the speed
+ of this operation will be proportional to the size of the list. If the list is
+ empty the return value will be this object.
+ If you're planning on appending a number of items to your list, it's much more
+ efficient to use the Appender class than to repeatedly call getLast() to find the end.
+ */
+ LinkedListPointer& getLast() noexcept
+ {
+ LinkedListPointer* l = this;
+
+ while (l->item != nullptr)
+ l = &(l->item->nextListItem);
+
+ return *l;
+ }
+
+ /** Returns the number of items in the list.
+ Obviously with a simple linked list, getting the size involves iterating the list, so
+ this can be a lengthy operation - be careful when using this method in your code.
+ */
+ int size() const noexcept
+ {
+ int total = 0;
+
+ for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
+ ++total;
+
+ return total;
+ }
+
+ /** Returns the item at a given index in the list.
+ Since the only way to find an item is to iterate the list, this operation can obviously
+ be slow, depending on its size, so you should be careful when using this in algorithms.
+ */
+ LinkedListPointer& operator[] (int index) noexcept
+ {
+ LinkedListPointer* l = this;
+
+ while (--index >= 0 && l->item != nullptr)
+ l = &(l->item->nextListItem);
+
+ return *l;
+ }
+
+ /** Returns the item at a given index in the list.
+ Since the only way to find an item is to iterate the list, this operation can obviously
+ be slow, depending on its size, so you should be careful when using this in algorithms.
+ */
+ const LinkedListPointer& operator[] (int index) const noexcept
+ {
+ const LinkedListPointer* l = this;
+
+ while (--index >= 0 && l->item != nullptr)
+ l = &(l->item->nextListItem);
+
+ return *l;
+ }
+
+ /** Returns true if the list contains the given item. */
+ bool contains (const ObjectType* const itemToLookFor) const noexcept
+ {
+ for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
+ if (itemToLookFor == i)
+ return true;
+
+ return false;
+ }
+
+ //==============================================================================
+ /** Inserts an item into the list, placing it before the item that this pointer
+ currently points to.
+ */
+ void insertNext (ObjectType* const newItem)
+ {
+ jassert (newItem != nullptr);
+ jassert (newItem->nextListItem == nullptr);
+ newItem->nextListItem = item;
+ item = newItem;
+ }
+
+ /** Inserts an item at a numeric index in the list.
+ Obviously this will involve iterating the list to find the item at the given index,
+ so be careful about the impact this may have on execution time.
+ */
+ void insertAtIndex (int index, ObjectType* newItem)
+ {
+ jassert (newItem != nullptr);
+ LinkedListPointer* l = this;
+
+ while (index != 0 && l->item != nullptr)
+ {
+ l = &(l->item->nextListItem);
+ --index;
+ }
+
+ l->insertNext (newItem);
+ }
+
+ /** Replaces the object that this pointer points to, appending the rest of the list to
+ the new object, and returning the old one.
+ */
+ ObjectType* replaceNext (ObjectType* const newItem) noexcept
+ {
+ jassert (newItem != nullptr);
+ jassert (newItem->nextListItem == nullptr);
+
+ ObjectType* const oldItem = item;
+ item = newItem;
+ item->nextListItem = oldItem->nextListItem.item;
+ oldItem->nextListItem.item = nullptr;
+ return oldItem;
+ }
+
+ /** Adds an item to the end of the list.
+
+ This operation involves iterating the whole list, so can be slow - if you need to
+ append a number of items to your list, it's much more efficient to use the Appender
+ class than to repeatedly call append().
+ */
+ void append (ObjectType* const newItem)
+ {
+ getLast().item = newItem;
+ }
+
+ /** Creates copies of all the items in another list and adds them to this one.
+ This will use the ObjectType's copy constructor to try to create copies of each
+ item in the other list, and appends them to this list.
+ */
+ void addCopyOfList (const LinkedListPointer& other)
+ {
+ LinkedListPointer* insertPoint = this;
+
+ for (ObjectType* i = other.item; i != nullptr; i = i->nextListItem)
+ {
+ insertPoint->insertNext (new ObjectType (*i));
+ insertPoint = &(insertPoint->item->nextListItem);
+ }
+ }
+
+ /** Removes the head item from the list.
+ This won't delete the object that is removed, but returns it, so the caller can
+ delete it if necessary.
+ */
+ ObjectType* removeNext() noexcept
+ {
+ ObjectType* const oldItem = item;
+
+ if (oldItem != nullptr)
+ {
+ item = oldItem->nextListItem;
+ oldItem->nextListItem.item = nullptr;
+ }
+
+ return oldItem;
+ }
+
+ /** Removes a specific item from the list.
+ Note that this will not delete the item, it simply unlinks it from the list.
+ */
+ void remove (ObjectType* const itemToRemove)
+ {
+ if (LinkedListPointer* const l = findPointerTo (itemToRemove))
+ l->removeNext();
+ }
+
+ /** Iterates the list, calling the delete operator on all of its elements and
+ leaving this pointer empty.
+ */
+ void deleteAll()
+ {
+ while (item != nullptr)
+ {
+ ObjectType* const oldItem = item;
+ item = oldItem->nextListItem;
+ delete oldItem;
+ }
+ }
+
+ /** Finds a pointer to a given item.
+ If the item is found in the list, this returns the pointer that points to it. If
+ the item isn't found, this returns null.
+ */
+ LinkedListPointer* findPointerTo (ObjectType* const itemToLookFor) noexcept
+ {
+ LinkedListPointer* l = this;
+
+ while (l->item != nullptr)
+ {
+ if (l->item == itemToLookFor)
+ return l;
+
+ l = &(l->item->nextListItem);
+ }
+
+ return nullptr;
+ }
+
+ /** Copies the items in the list to an array.
+ The destArray must contain enough elements to hold the entire list - no checks are
+ made for this!
+ */
+ void copyToArray (ObjectType** destArray) const noexcept
+ {
+ jassert (destArray != nullptr);
+
+ for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
+ *destArray++ = i;
+ }
+
+ /** Swaps this pointer with another one */
+ void swapWith (LinkedListPointer& other) noexcept
+ {
+ std::swap (item, other.item);
+ }
+
+ //==============================================================================
+ /**
+ Allows efficient repeated insertions into a list.
+
+ You can create an Appender object which points to the last element in your
+ list, and then repeatedly call Appender::append() to add items to the end
+ of the list in O(1) time.
+ */
+ class Appender
+ {
+ public:
+ /** Creates an appender which will add items to the given list.
+ */
+ Appender (LinkedListPointer& endOfListPointer) noexcept
+ : endOfList (&endOfListPointer)
+ {
+ // This can only be used to add to the end of a list.
+ jassert (endOfListPointer.item == nullptr);
+ }
+
+ /** Appends an item to the list. */
+ void append (ObjectType* const newItem) noexcept
+ {
+ *endOfList = newItem;
+ endOfList = &(newItem->nextListItem);
+ }
+
+ private:
+ LinkedListPointer* endOfList;
+
+ JUCE_DECLARE_NON_COPYABLE (Appender)
+ };
+
+private:
+ //==============================================================================
+ ObjectType* item;
+
+ JUCE_DECLARE_NON_COPYABLE (LinkedListPointer)
+};
+
+
+#endif // JUCE_LINKEDLISTPOINTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.cpp
new file mode 100644
index 0000000..c4e198d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.cpp
@@ -0,0 +1,271 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+struct NamedValueSet::NamedValue
+{
+ NamedValue() noexcept {}
+ NamedValue (Identifier n, const var& v) : name (n), value (v) {}
+ NamedValue (const NamedValue& other) : name (other.name), value (other.value) {}
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ NamedValue (NamedValue&& other) noexcept
+ : name (static_cast<Identifier&&> (other.name)),
+ value (static_cast<var&&> (other.value))
+ {
+ }
+
+ NamedValue (Identifier n, var&& v) : name (n), value (static_cast<var&&> (v))
+ {
+ }
+
+ NamedValue& operator= (NamedValue&& other) noexcept
+ {
+ name = static_cast<Identifier&&> (other.name);
+ value = static_cast<var&&> (other.value);
+ return *this;
+ }
+ #endif
+
+ bool operator== (const NamedValue& other) const noexcept { return name == other.name && value == other.value; }
+ bool operator!= (const NamedValue& other) const noexcept { return ! operator== (other); }
+
+ Identifier name;
+ var value;
+};
+
+//==============================================================================
+NamedValueSet::NamedValueSet() noexcept
+{
+}
+
+NamedValueSet::NamedValueSet (const NamedValueSet& other)
+ : values (other.values)
+{
+}
+
+NamedValueSet& NamedValueSet::operator= (const NamedValueSet& other)
+{
+ clear();
+ values = other.values;
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+NamedValueSet::NamedValueSet (NamedValueSet&& other) noexcept
+ : values (static_cast <Array<NamedValue>&&> (other.values))
+{
+}
+
+NamedValueSet& NamedValueSet::operator= (NamedValueSet&& other) noexcept
+{
+ other.values.swapWith (values);
+ return *this;
+}
+#endif
+
+NamedValueSet::~NamedValueSet()
+{
+ clear();
+}
+
+void NamedValueSet::clear()
+{
+ values.clear();
+}
+
+bool NamedValueSet::operator== (const NamedValueSet& other) const
+{
+ return values == other.values;
+}
+
+bool NamedValueSet::operator!= (const NamedValueSet& other) const
+{
+ return ! operator== (other);
+}
+
+int NamedValueSet::size() const noexcept
+{
+ return values.size();
+}
+
+const var& NamedValueSet::operator[] (const Identifier& name) const
+{
+ if (const var* v = getVarPointer (name))
+ return *v;
+
+ return var::null;
+}
+
+var NamedValueSet::getWithDefault (const Identifier& name, const var& defaultReturnValue) const
+{
+ if (const var* const v = getVarPointer (name))
+ return *v;
+
+ return defaultReturnValue;
+}
+
+var* NamedValueSet::getVarPointer (const Identifier& name) const noexcept
+{
+ for (NamedValue* e = values.end(), *i = values.begin(); i != e; ++i)
+ if (i->name == name)
+ return &(i->value);
+
+ return nullptr;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+bool NamedValueSet::set (Identifier name, var&& newValue)
+{
+ if (var* const v = getVarPointer (name))
+ {
+ if (v->equalsWithSameType (newValue))
+ return false;
+
+ *v = static_cast<var&&> (newValue);
+ return true;
+ }
+
+ values.add (NamedValue (name, static_cast<var&&> (newValue)));
+ return true;
+}
+#endif
+
+bool NamedValueSet::set (Identifier name, const var& newValue)
+{
+ if (var* const v = getVarPointer (name))
+ {
+ if (v->equalsWithSameType (newValue))
+ return false;
+
+ *v = newValue;
+ return true;
+ }
+
+ values.add (NamedValue (name, newValue));
+ return true;
+}
+
+bool NamedValueSet::contains (const Identifier& name) const
+{
+ return getVarPointer (name) != nullptr;
+}
+
+int NamedValueSet::indexOf (const Identifier& name) const noexcept
+{
+ const int numValues = values.size();
+
+ for (int i = 0; i < numValues; ++i)
+ if (values.getReference(i).name == name)
+ return i;
+
+ return -1;
+}
+
+bool NamedValueSet::remove (const Identifier& name)
+{
+ const int numValues = values.size();
+
+ for (int i = 0; i < numValues; ++i)
+ {
+ if (values.getReference(i).name == name)
+ {
+ values.remove (i);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Identifier NamedValueSet::getName (const int index) const noexcept
+{
+ if (isPositiveAndBelow (index, values.size()))
+ return values.getReference (index).name;
+
+ jassertfalse;
+ return Identifier();
+}
+
+const var& NamedValueSet::getValueAt (const int index) const noexcept
+{
+ if (isPositiveAndBelow (index, values.size()))
+ return values.getReference (index).value;
+
+ jassertfalse;
+ return var::null;
+}
+
+var* NamedValueSet::getVarPointerAt (int index) const noexcept
+{
+ if (isPositiveAndBelow (index, values.size()))
+ return &(values.getReference (index).value);
+
+ return nullptr;
+}
+
+void NamedValueSet::setFromXmlAttributes (const XmlElement& xml)
+{
+ values.clearQuick();
+
+ for (const XmlElement::XmlAttributeNode* att = xml.attributes; att != nullptr; att = att->nextListItem)
+ {
+ if (att->name.toString().startsWith ("base64:"))
+ {
+ MemoryBlock mb;
+
+ if (mb.fromBase64Encoding (att->value))
+ {
+ values.add (NamedValue (att->name.toString().substring (7), var (mb)));
+ continue;
+ }
+ }
+
+ values.add (NamedValue (att->name, var (att->value)));
+ }
+}
+
+void NamedValueSet::copyToXmlAttributes (XmlElement& xml) const
+{
+ for (NamedValue* e = values.end(), *i = values.begin(); i != e; ++i)
+ {
+ if (const MemoryBlock* mb = i->value.getBinaryData())
+ {
+ xml.setAttribute ("base64:" + i->name.toString(), mb->toBase64Encoding());
+ }
+ else
+ {
+ // These types can't be stored as XML!
+ jassert (! i->value.isObject());
+ jassert (! i->value.isMethod());
+ jassert (! i->value.isArray());
+
+ xml.setAttribute (i->name.toString(),
+ i->value.toString());
+ }
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.h
new file mode 100644
index 0000000..0216326
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_NamedValueSet.h
@@ -0,0 +1,145 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_NAMEDVALUESET_H_INCLUDED
+#define JUCE_NAMEDVALUESET_H_INCLUDED
+
+
+//==============================================================================
+/** Holds a set of named var objects.
+
+ This can be used as a basic structure to hold a set of var object, which can
+ be retrieved by using their identifier.
+*/
+class JUCE_API NamedValueSet
+{
+public:
+ /** Creates an empty set. */
+ NamedValueSet() noexcept;
+
+ /** Creates a copy of another set. */
+ NamedValueSet (const NamedValueSet&);
+
+ /** Replaces this set with a copy of another set. */
+ NamedValueSet& operator= (const NamedValueSet&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ NamedValueSet (NamedValueSet&&) noexcept;
+ NamedValueSet& operator= (NamedValueSet&&) noexcept;
+ #endif
+
+ /** Destructor. */
+ ~NamedValueSet();
+
+ bool operator== (const NamedValueSet&) const;
+ bool operator!= (const NamedValueSet&) const;
+
+ //==============================================================================
+ /** Returns the total number of values that the set contains. */
+ int size() const noexcept;
+
+ /** Returns the value of a named item.
+ If the name isn't found, this will return a void variant.
+ @see getProperty
+ */
+ const var& operator[] (const Identifier& name) const;
+
+ /** Tries to return the named value, but if no such value is found, this will
+ instead return the supplied default value.
+ */
+ var getWithDefault (const Identifier& name, const var& defaultReturnValue) const;
+
+ /** Changes or adds a named value.
+ @returns true if a value was changed or added; false if the
+ value was already set the value passed-in.
+ */
+ bool set (Identifier name, const var& newValue);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Changes or adds a named value.
+ @returns true if a value was changed or added; false if the
+ value was already set the value passed-in.
+ */
+ bool set (Identifier name, var&& newValue);
+ #endif
+
+ /** Returns true if the set contains an item with the specified name. */
+ bool contains (const Identifier& name) const;
+
+ /** Removes a value from the set.
+ @returns true if a value was removed; false if there was no value
+ with the name that was given.
+ */
+ bool remove (const Identifier& name);
+
+ /** Returns the name of the value at a given index.
+ The index must be between 0 and size() - 1.
+ */
+ Identifier getName (int index) const noexcept;
+
+ /** Returns a pointer to the var that holds a named value, or null if there is
+ no value with this name.
+
+ Do not use this method unless you really need access to the internal var object
+ for some reason - for normal reading and writing always prefer operator[]() and set().
+ */
+ var* getVarPointer (const Identifier& name) const noexcept;
+
+ /** Returns the value of the item at a given index.
+ The index must be between 0 and size() - 1.
+ */
+ const var& getValueAt (int index) const noexcept;
+
+ /** Returns the value of the item at a given index.
+ The index must be between 0 and size() - 1, or this will return a nullptr
+ */
+ var* getVarPointerAt (int index) const noexcept;
+
+ /** Returns the index of the given name, or -1 if it's not found. */
+ int indexOf (const Identifier& name) const noexcept;
+
+ /** Removes all values. */
+ void clear();
+
+ //==============================================================================
+ /** Sets properties to the values of all of an XML element's attributes. */
+ void setFromXmlAttributes (const XmlElement& xml);
+
+ /** Sets attributes in an XML element corresponding to each of this object's
+ properties.
+ */
+ void copyToXmlAttributes (XmlElement& xml) const;
+
+private:
+ //==============================================================================
+ struct NamedValue;
+ Array<NamedValue> values;
+};
+
+
+#endif // JUCE_NAMEDVALUESET_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_OwnedArray.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_OwnedArray.h
new file mode 100644
index 0000000..a116df8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_OwnedArray.h
@@ -0,0 +1,897 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_OWNEDARRAY_H_INCLUDED
+#define JUCE_OWNEDARRAY_H_INCLUDED
+
+
+//==============================================================================
+/** An array designed for holding objects.
+
+ This holds a list of pointers to objects, and will automatically
+ delete the objects when they are removed from the array, or when the
+ array is itself deleted.
+
+ Declare it in the form: OwnedArray<MyObjectClass>
+
+ ..and then add new objects, e.g. myOwnedArray.add (new MyObjectClass());
+
+ After adding objects, they are 'owned' by the array and will be deleted when
+ removed or replaced.
+
+ To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
+ TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
+
+ @see Array, ReferenceCountedArray, StringArray, CriticalSection
+*/
+template <class ObjectClass,
+ class TypeOfCriticalSectionToUse = DummyCriticalSection>
+
+class OwnedArray
+{
+public:
+ //==============================================================================
+ /** Creates an empty array. */
+ OwnedArray() noexcept
+ : numUsed (0)
+ {
+ }
+
+ /** Deletes the array and also deletes any objects inside it.
+
+ To get rid of the array without deleting its objects, use its
+ clear (false) method before deleting it.
+ */
+ ~OwnedArray()
+ {
+ deleteAllObjects();
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ OwnedArray (OwnedArray&& other) noexcept
+ : data (static_cast <ArrayAllocationBase <ObjectClass*, TypeOfCriticalSectionToUse>&&> (other.data)),
+ numUsed (other.numUsed)
+ {
+ other.numUsed = 0;
+ }
+
+ OwnedArray& operator= (OwnedArray&& other) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ deleteAllObjects();
+
+ data = static_cast <ArrayAllocationBase <ObjectClass*, TypeOfCriticalSectionToUse>&&> (other.data);
+ numUsed = other.numUsed;
+ other.numUsed = 0;
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Clears the array, optionally deleting the objects inside it first. */
+ void clear (bool deleteObjects = true)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (deleteObjects)
+ deleteAllObjects();
+
+ data.setAllocatedSize (0);
+ numUsed = 0;
+ }
+
+ //==============================================================================
+ /** Clears the array, optionally deleting the objects inside it first. */
+ void clearQuick (bool deleteObjects)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (deleteObjects)
+ deleteAllObjects();
+
+ numUsed = 0;
+ }
+
+ //==============================================================================
+ /** Returns the number of items currently in the array.
+ @see operator[]
+ */
+ inline int size() const noexcept
+ {
+ return numUsed;
+ }
+
+ /** Returns a pointer to the object at this index in the array.
+
+ If the index is out-of-range, this will return a null pointer, (and
+ it could be null anyway, because it's ok for the array to hold null
+ pointers as well as objects).
+
+ @see getUnchecked
+ */
+ inline ObjectClass* operator[] (const int index) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ if (isPositiveAndBelow (index, numUsed))
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ return nullptr;
+ }
+
+ /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range.
+
+ This is a faster and less safe version of operator[] which doesn't check the index passed in, so
+ it can be used when you're sure the index is always going to be legal.
+ */
+ inline ObjectClass* getUnchecked (const int index) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ /** Returns a pointer to the first object in the array.
+
+ This will return a null pointer if the array's empty.
+ @see getLast
+ */
+ inline ObjectClass* getFirst() const noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [0];
+ }
+
+ return nullptr;
+ }
+
+ /** Returns a pointer to the last object in the array.
+
+ This will return a null pointer if the array's empty.
+ @see getFirst
+ */
+ inline ObjectClass* getLast() const noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [numUsed - 1];
+ }
+
+ return nullptr;
+ }
+
+ /** Returns a pointer to the actual array data.
+ This pointer will only be valid until the next time a non-const method
+ is called on the array.
+ */
+ inline ObjectClass** getRawDataPointer() noexcept
+ {
+ return data.elements;
+ }
+
+ //==============================================================================
+ /** Returns a pointer to the first element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ObjectClass** begin() const noexcept
+ {
+ return data.elements;
+ }
+
+ /** Returns a pointer to the element which follows the last element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ObjectClass** end() const noexcept
+ {
+ #if JUCE_DEBUG
+ if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
+ return data.elements;
+ #endif
+
+ return data.elements + numUsed;
+ }
+
+ //==============================================================================
+ /** Finds the index of an object which might be in the array.
+
+ @param objectToLookFor the object to look for
+ @returns the index at which the object was found, or -1 if it's not found
+ */
+ int indexOf (const ObjectClass* objectToLookFor) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ ObjectClass* const* e = data.elements.getData();
+ ObjectClass* const* const end_ = e + numUsed;
+
+ for (; e != end_; ++e)
+ if (objectToLookFor == *e)
+ return static_cast <int> (e - data.elements.getData());
+
+ return -1;
+ }
+
+ /** Returns true if the array contains a specified object.
+
+ @param objectToLookFor the object to look for
+ @returns true if the object is in the array
+ */
+ bool contains (const ObjectClass* objectToLookFor) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ ObjectClass* const* e = data.elements.getData();
+ ObjectClass* const* const end_ = e + numUsed;
+
+ for (; e != end_; ++e)
+ if (objectToLookFor == *e)
+ return true;
+
+ return false;
+ }
+
+ //==============================================================================
+ /** Appends a new object to the end of the array.
+
+ Note that the this object will be deleted by the OwnedArray when it
+ is removed, so be careful not to delete it somewhere else.
+
+ Also be careful not to add the same object to the array more than once,
+ as this will obviously cause deletion of dangling pointers.
+
+ @param newObject the new object to add to the array
+ @returns the new object that was added
+ @see set, insert, addIfNotAlreadyThere, addSorted
+ */
+ ObjectClass* add (ObjectClass* newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+ data.elements [numUsed++] = newObject;
+ return newObject;
+ }
+
+ /** Inserts a new object into the array at the given index.
+
+ Note that the this object will be deleted by the OwnedArray when it
+ is removed, so be careful not to delete it somewhere else.
+
+ If the index is less than 0 or greater than the size of the array, the
+ element will be added to the end of the array.
+ Otherwise, it will be inserted into the array, moving all the later elements
+ along to make room.
+
+ Be careful not to add the same object to the array more than once,
+ as this will obviously cause deletion of dangling pointers.
+
+ @param indexToInsertAt the index at which the new element should be inserted
+ @param newObject the new object to add to the array
+ @returns the new object that was added
+ @see add, addSorted, addIfNotAlreadyThere, set
+ */
+ ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject) noexcept
+ {
+ if (indexToInsertAt < 0)
+ return add (newObject);
+
+ const ScopedLockType lock (getLock());
+
+ if (indexToInsertAt > numUsed)
+ indexToInsertAt = numUsed;
+
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+
+ ObjectClass** const e = data.elements + indexToInsertAt;
+ const int numToMove = numUsed - indexToInsertAt;
+
+ if (numToMove > 0)
+ memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
+
+ *e = newObject;
+ ++numUsed;
+ return newObject;
+ }
+
+ /** Inserts an array of values into this array at a given position.
+
+ If the index is less than 0 or greater than the size of the array, the
+ new elements will be added to the end of the array.
+ Otherwise, they will be inserted into the array, moving all the later elements
+ along to make room.
+
+ @param indexToInsertAt the index at which the first new element should be inserted
+ @param newObjects the new values to add to the array
+ @param numberOfElements how many items are in the array
+ @see insert, add, addSorted, set
+ */
+ void insertArray (int indexToInsertAt,
+ ObjectClass* const* newObjects,
+ int numberOfElements)
+ {
+ if (numberOfElements > 0)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + numberOfElements);
+ ObjectClass** insertPos = data.elements;
+
+ if (isPositiveAndBelow (indexToInsertAt, numUsed))
+ {
+ insertPos += indexToInsertAt;
+ const size_t numberToMove = (size_t) (numUsed - indexToInsertAt);
+ memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ObjectClass*));
+ }
+ else
+ {
+ insertPos += numUsed;
+ }
+
+ numUsed += numberOfElements;
+
+ while (--numberOfElements >= 0)
+ *insertPos++ = *newObjects++;
+ }
+ }
+
+ /** Appends a new object at the end of the array as long as the array doesn't
+ already contain it.
+
+ If the array already contains a matching object, nothing will be done.
+
+ @param newObject the new object to add to the array
+ @returns the new object that was added
+ */
+ ObjectClass* addIfNotAlreadyThere (ObjectClass* newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (! contains (newObject))
+ add (newObject);
+
+ return newObject;
+ }
+
+ /** Replaces an object in the array with a different one.
+
+ If the index is less than zero, this method does nothing.
+ If the index is beyond the end of the array, the new object is added to the end of the array.
+
+ Be careful not to add the same object to the array more than once,
+ as this will obviously cause deletion of dangling pointers.
+
+ @param indexToChange the index whose value you want to change
+ @param newObject the new value to set for this index.
+ @param deleteOldElement whether to delete the object that's being replaced with the new one
+ @see add, insert, remove
+ */
+ ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
+ {
+ if (indexToChange >= 0)
+ {
+ ScopedPointer<ObjectClass> toDelete;
+
+ {
+ const ScopedLockType lock (getLock());
+
+ if (indexToChange < numUsed)
+ {
+ if (deleteOldElement)
+ {
+ toDelete = data.elements [indexToChange];
+
+ if (toDelete == newObject)
+ toDelete.release();
+ }
+
+ data.elements [indexToChange] = newObject;
+ }
+ else
+ {
+ data.ensureAllocatedSize (numUsed + 1);
+ data.elements [numUsed++] = newObject;
+ }
+ }
+ }
+ else
+ {
+ jassertfalse; // you're trying to set an object at a negative index, which doesn't have
+ // any effect - but since the object is not being added, it may be leaking..
+ }
+
+ return newObject;
+ }
+
+ /** Adds elements from another array to the end of this array.
+
+ @param arrayToAddFrom the array from which to copy the elements
+ @param startIndex the first element of the other array to start copying from
+ @param numElementsToAdd how many elements to add from the other array. If this
+ value is negative or greater than the number of available elements,
+ all available elements will be copied.
+ @see add
+ */
+ template <class OtherArrayType>
+ void addArray (const OtherArrayType& arrayToAddFrom,
+ int startIndex = 0,
+ int numElementsToAdd = -1)
+ {
+ const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
+ numElementsToAdd = arrayToAddFrom.size() - startIndex;
+
+ data.ensureAllocatedSize (numUsed + numElementsToAdd);
+ jassert (numElementsToAdd <= 0 || data.elements != nullptr);
+
+ while (--numElementsToAdd >= 0)
+ {
+ data.elements [numUsed] = arrayToAddFrom.getUnchecked (startIndex++);
+ ++numUsed;
+ }
+ }
+
+ /** Adds copies of the elements in another array to the end of this array.
+
+ The other array must be either an OwnedArray of a compatible type of object, or an Array
+ containing pointers to the same kind of object. The objects involved must provide
+ a copy constructor, and this will be used to create new copies of each element, and
+ add them to this array.
+
+ @param arrayToAddFrom the array from which to copy the elements
+ @param startIndex the first element of the other array to start copying from
+ @param numElementsToAdd how many elements to add from the other array. If this
+ value is negative or greater than the number of available elements,
+ all available elements will be copied.
+ @see add
+ */
+ template <class OtherArrayType>
+ void addCopiesOf (const OtherArrayType& arrayToAddFrom,
+ int startIndex = 0,
+ int numElementsToAdd = -1)
+ {
+ const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
+ numElementsToAdd = arrayToAddFrom.size() - startIndex;
+
+ data.ensureAllocatedSize (numUsed + numElementsToAdd);
+ jassert (numElementsToAdd <= 0 || data.elements != nullptr);
+
+ while (--numElementsToAdd >= 0)
+ data.elements [numUsed++] = createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++));
+ }
+
+ /** Inserts a new object into the array assuming that the array is sorted.
+
+ This will use a comparator to find the position at which the new object
+ should go. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator to use to compare the elements - see the sort method
+ for details about this object's structure
+ @param newObject the new object to insert to the array
+ @returns the index at which the new object was added
+ @see add, sort, indexOfSorted
+ */
+ template <class ElementComparator>
+ int addSorted (ElementComparator& comparator, ObjectClass* const newObject) noexcept
+ {
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+ const ScopedLockType lock (getLock());
+ const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
+ insert (index, newObject);
+ return index;
+ }
+
+ /** Finds the index of an object in the array, assuming that the array is sorted.
+
+ This will use a comparator to do a binary-chop to find the index of the given
+ element, if it exists. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator to use to compare the elements - see the sort()
+ method for details about the form this object should take
+ @param objectToLookFor the object to search for
+ @returns the index of the element, or -1 if it's not found
+ @see addSorted, sort
+ */
+ template <typename ElementComparator>
+ int indexOfSorted (ElementComparator& comparator, const ObjectClass* const objectToLookFor) const noexcept
+ {
+ (void) comparator;
+ const ScopedLockType lock (getLock());
+ int s = 0, e = numUsed;
+
+ while (s < e)
+ {
+ if (comparator.compareElements (objectToLookFor, data.elements [s]) == 0)
+ return s;
+
+ const int halfway = (s + e) / 2;
+ if (halfway == s)
+ break;
+
+ if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
+ s = halfway;
+ else
+ e = halfway;
+ }
+
+ return -1;
+ }
+
+ //==============================================================================
+ /** Removes an object from the array.
+
+ This will remove the object at a given index (optionally also
+ deleting it) and move back all the subsequent objects to close the gap.
+ If the index passed in is out-of-range, nothing will happen.
+
+ @param indexToRemove the index of the element to remove
+ @param deleteObject whether to delete the object that is removed
+ @see removeObject, removeRange
+ */
+ void remove (int indexToRemove, bool deleteObject = true)
+ {
+ ScopedPointer<ObjectClass> toDelete;
+
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToRemove, numUsed))
+ {
+ ObjectClass** const e = data.elements + indexToRemove;
+
+ if (deleteObject)
+ toDelete = *e;
+
+ --numUsed;
+ const int numToShift = numUsed - indexToRemove;
+
+ if (numToShift > 0)
+ memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numToShift);
+ }
+ }
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+
+ /** Removes and returns an object from the array without deleting it.
+
+ This will remove the object at a given index and return it, moving back all
+ the subsequent objects to close the gap. If the index passed in is out-of-range,
+ nothing will happen.
+
+ @param indexToRemove the index of the element to remove
+ @see remove, removeObject, removeRange
+ */
+ ObjectClass* removeAndReturn (int indexToRemove)
+ {
+ ObjectClass* removedItem = nullptr;
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToRemove, numUsed))
+ {
+ ObjectClass** const e = data.elements + indexToRemove;
+ removedItem = *e;
+
+ --numUsed;
+ const int numToShift = numUsed - indexToRemove;
+
+ if (numToShift > 0)
+ memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numToShift);
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+
+ return removedItem;
+ }
+
+ /** Removes a specified object from the array.
+
+ If the item isn't found, no action is taken.
+
+ @param objectToRemove the object to try to remove
+ @param deleteObject whether to delete the object (if it's found)
+ @see remove, removeRange
+ */
+ void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
+ {
+ const ScopedLockType lock (getLock());
+ ObjectClass** const e = data.elements.getData();
+
+ for (int i = 0; i < numUsed; ++i)
+ {
+ if (objectToRemove == e[i])
+ {
+ remove (i, deleteObject);
+ break;
+ }
+ }
+ }
+
+ /** Removes a range of objects from the array.
+
+ This will remove a set of objects, starting from the given index,
+ and move any subsequent elements down to close the gap.
+
+ If the range extends beyond the bounds of the array, it will
+ be safely clipped to the size of the array.
+
+ @param startIndex the index of the first object to remove
+ @param numberToRemove how many objects should be removed
+ @param deleteObjects whether to delete the objects that get removed
+ @see remove, removeObject
+ */
+ void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
+ {
+ const ScopedLockType lock (getLock());
+ const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
+ startIndex = jlimit (0, numUsed, startIndex);
+
+ if (endIndex > startIndex)
+ {
+ if (deleteObjects)
+ {
+ for (int i = startIndex; i < endIndex; ++i)
+ {
+ ContainerDeletePolicy<ObjectClass>::destroy (data.elements [i]);
+ data.elements [i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
+ }
+ }
+
+ const int rangeSize = endIndex - startIndex;
+ ObjectClass** e = data.elements + startIndex;
+ int numToShift = numUsed - endIndex;
+ numUsed -= rangeSize;
+
+ while (--numToShift >= 0)
+ {
+ *e = e [rangeSize];
+ ++e;
+ }
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+ }
+
+ /** Removes the last n objects from the array.
+
+ @param howManyToRemove how many objects to remove from the end of the array
+ @param deleteObjects whether to also delete the objects that are removed
+ @see remove, removeObject, removeRange
+ */
+ void removeLast (int howManyToRemove = 1,
+ bool deleteObjects = true)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (howManyToRemove >= numUsed)
+ clear (deleteObjects);
+ else
+ removeRange (numUsed - howManyToRemove, howManyToRemove, deleteObjects);
+ }
+
+ /** Swaps a pair of objects in the array.
+
+ If either of the indexes passed in is out-of-range, nothing will happen,
+ otherwise the two objects at these positions will be exchanged.
+ */
+ void swap (int index1,
+ int index2) noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (index1, numUsed)
+ && isPositiveAndBelow (index2, numUsed))
+ {
+ std::swap (data.elements [index1],
+ data.elements [index2]);
+ }
+ }
+
+ /** Moves one of the objects to a different position.
+
+ This will move the object to a specified index, shuffling along
+ any intervening elements as required.
+
+ So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
+ move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
+
+ @param currentIndex the index of the object to be moved. If this isn't a
+ valid index, then nothing will be done
+ @param newIndex the index at which you'd like this object to end up. If this
+ is less than zero, it will be moved to the end of the array
+ */
+ void move (int currentIndex, int newIndex) noexcept
+ {
+ if (currentIndex != newIndex)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (currentIndex, numUsed))
+ {
+ if (! isPositiveAndBelow (newIndex, numUsed))
+ newIndex = numUsed - 1;
+
+ ObjectClass* const value = data.elements [currentIndex];
+
+ if (newIndex > currentIndex)
+ {
+ memmove (data.elements + currentIndex,
+ data.elements + currentIndex + 1,
+ sizeof (ObjectClass*) * (size_t) (newIndex - currentIndex));
+ }
+ else
+ {
+ memmove (data.elements + newIndex + 1,
+ data.elements + newIndex,
+ sizeof (ObjectClass*) * (size_t) (currentIndex - newIndex));
+ }
+
+ data.elements [newIndex] = value;
+ }
+ }
+ }
+
+ /** This swaps the contents of this array with those of another array.
+
+ If you need to exchange two arrays, this is vastly quicker than using copy-by-value
+ because it just swaps their internal pointers.
+ */
+ template <class OtherArrayType>
+ void swapWith (OtherArrayType& otherArray) noexcept
+ {
+ const ScopedLockType lock1 (getLock());
+ const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
+ data.swapWith (otherArray.data);
+ std::swap (numUsed, otherArray.numUsed);
+ }
+
+ //==============================================================================
+ /** Reduces the amount of storage being used by the array.
+
+ Arrays typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads() noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.shrinkToNoMoreThan (numUsed);
+ }
+
+ /** Increases the array's internal storage to hold a minimum number of elements.
+
+ Calling this before adding a large known number of elements means that
+ the array won't have to keep dynamically resizing itself as the elements
+ are added, and it'll therefore be more efficient.
+ */
+ void ensureStorageAllocated (const int minNumElements) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (minNumElements);
+ }
+
+ //==============================================================================
+ /** Sorts the elements in the array.
+
+ This will use a comparator object to sort the elements into order. The object
+ passed must have a method of the form:
+ @code
+ int compareElements (ElementType first, ElementType second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator the comparator to use for comparing elements.
+ @param retainOrderOfEquivalentItems if this is true, then items
+ which the comparator says are equivalent will be
+ kept in the order in which they currently appear
+ in the array. This is slower to perform, but may
+ be important in some cases. If it's false, a faster
+ algorithm is used, but equivalent elements may be
+ rearranged.
+ @see sortArray, indexOfSorted
+ */
+ template <class ElementComparator>
+ void sort (ElementComparator& comparator,
+ bool retainOrderOfEquivalentItems = false) const noexcept
+ {
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+
+ const ScopedLockType lock (getLock());
+ sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
+ }
+
+ //==============================================================================
+ /** Returns the CriticalSection that locks this array.
+ To lock, you can call getLock().enter() and getLock().exit(), or preferably use
+ an object of ScopedLockType as an RAII lock for it.
+ */
+ inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; }
+
+ /** Returns the type of scoped lock to use for locking this array */
+ typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
+
+
+ //==============================================================================
+ #ifndef DOXYGEN
+ // Note that the swapWithArray method has been replaced by a more flexible templated version,
+ // and renamed "swapWith" to be more consistent with the names used in other classes.
+ JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
+ #endif
+
+private:
+ //==============================================================================
+ ArrayAllocationBase <ObjectClass*, TypeOfCriticalSectionToUse> data;
+ int numUsed;
+
+ void deleteAllObjects()
+ {
+ while (numUsed > 0)
+ ContainerDeletePolicy<ObjectClass>::destroy (data.elements [--numUsed]);
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
+};
+
+
+#endif // JUCE_OWNEDARRAY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.cpp
new file mode 100644
index 0000000..6b02baf
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.cpp
@@ -0,0 +1,219 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+PropertySet::PropertySet (const bool ignoreCaseOfKeyNames)
+ : properties (ignoreCaseOfKeyNames),
+ fallbackProperties (nullptr),
+ ignoreCaseOfKeys (ignoreCaseOfKeyNames)
+{
+}
+
+PropertySet::PropertySet (const PropertySet& other)
+ : properties (other.properties),
+ fallbackProperties (other.fallbackProperties),
+ ignoreCaseOfKeys (other.ignoreCaseOfKeys)
+{
+}
+
+PropertySet& PropertySet::operator= (const PropertySet& other)
+{
+ properties = other.properties;
+ fallbackProperties = other.fallbackProperties;
+ ignoreCaseOfKeys = other.ignoreCaseOfKeys;
+
+ propertyChanged();
+ return *this;
+}
+
+PropertySet::~PropertySet()
+{
+}
+
+void PropertySet::clear()
+{
+ const ScopedLock sl (lock);
+
+ if (properties.size() > 0)
+ {
+ properties.clear();
+ propertyChanged();
+ }
+}
+
+String PropertySet::getValue (StringRef keyName, const String& defaultValue) const noexcept
+{
+ const ScopedLock sl (lock);
+
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index >= 0)
+ return properties.getAllValues() [index];
+
+ return fallbackProperties != nullptr ? fallbackProperties->getValue (keyName, defaultValue)
+ : defaultValue;
+}
+
+int PropertySet::getIntValue (StringRef keyName, const int defaultValue) const noexcept
+{
+ const ScopedLock sl (lock);
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index >= 0)
+ return properties.getAllValues() [index].getIntValue();
+
+ return fallbackProperties != nullptr ? fallbackProperties->getIntValue (keyName, defaultValue)
+ : defaultValue;
+}
+
+double PropertySet::getDoubleValue (StringRef keyName, const double defaultValue) const noexcept
+{
+ const ScopedLock sl (lock);
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index >= 0)
+ return properties.getAllValues()[index].getDoubleValue();
+
+ return fallbackProperties != nullptr ? fallbackProperties->getDoubleValue (keyName, defaultValue)
+ : defaultValue;
+}
+
+bool PropertySet::getBoolValue (StringRef keyName, const bool defaultValue) const noexcept
+{
+ const ScopedLock sl (lock);
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index >= 0)
+ return properties.getAllValues() [index].getIntValue() != 0;
+
+ return fallbackProperties != nullptr ? fallbackProperties->getBoolValue (keyName, defaultValue)
+ : defaultValue;
+}
+
+XmlElement* PropertySet::getXmlValue (StringRef keyName) const
+{
+ return XmlDocument::parse (getValue (keyName));
+}
+
+void PropertySet::setValue (const String& keyName, const var& v)
+{
+ jassert (keyName.isNotEmpty()); // shouldn't use an empty key name!
+
+ if (keyName.isNotEmpty())
+ {
+ const String value (v.toString());
+ const ScopedLock sl (lock);
+
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index < 0 || properties.getAllValues() [index] != value)
+ {
+ properties.set (keyName, value);
+ propertyChanged();
+ }
+ }
+}
+
+void PropertySet::removeValue (StringRef keyName)
+{
+ if (keyName.isNotEmpty())
+ {
+ const ScopedLock sl (lock);
+ const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
+
+ if (index >= 0)
+ {
+ properties.remove (keyName);
+ propertyChanged();
+ }
+ }
+}
+
+void PropertySet::setValue (const String& keyName, const XmlElement* const xml)
+{
+ setValue (keyName, xml == nullptr ? var()
+ : var (xml->createDocument ("", true)));
+}
+
+bool PropertySet::containsKey (StringRef keyName) const noexcept
+{
+ const ScopedLock sl (lock);
+ return properties.getAllKeys().contains (keyName, ignoreCaseOfKeys);
+}
+
+void PropertySet::addAllPropertiesFrom (const PropertySet& source)
+{
+ const ScopedLock sl (source.getLock());
+
+ for (int i = 0; i < source.properties.size(); ++i)
+ setValue (source.properties.getAllKeys() [i],
+ source.properties.getAllValues() [i]);
+}
+
+void PropertySet::setFallbackPropertySet (PropertySet* fallbackProperties_) noexcept
+{
+ const ScopedLock sl (lock);
+ fallbackProperties = fallbackProperties_;
+}
+
+XmlElement* PropertySet::createXml (const String& nodeName) const
+{
+ const ScopedLock sl (lock);
+ XmlElement* const xml = new XmlElement (nodeName);
+
+ for (int i = 0; i < properties.getAllKeys().size(); ++i)
+ {
+ XmlElement* const e = xml->createNewChildElement ("VALUE");
+ e->setAttribute ("name", properties.getAllKeys()[i]);
+ e->setAttribute ("val", properties.getAllValues()[i]);
+ }
+
+ return xml;
+}
+
+void PropertySet::restoreFromXml (const XmlElement& xml)
+{
+ const ScopedLock sl (lock);
+ clear();
+
+ forEachXmlChildElementWithTagName (xml, e, "VALUE")
+ {
+ if (e->hasAttribute ("name")
+ && e->hasAttribute ("val"))
+ {
+ properties.set (e->getStringAttribute ("name"),
+ e->getStringAttribute ("val"));
+ }
+ }
+
+ if (properties.size() > 0)
+ propertyChanged();
+}
+
+void PropertySet::propertyChanged()
+{
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.h
new file mode 100644
index 0000000..2a4ecb1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_PropertySet.h
@@ -0,0 +1,211 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_PROPERTYSET_H_INCLUDED
+#define JUCE_PROPERTYSET_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A set of named property values, which can be strings, integers, floating point, etc.
+
+ Effectively, this just wraps a StringPairArray in an interface that makes it easier
+ to load and save types other than strings.
+
+ See the PropertiesFile class for a subclass of this, which automatically broadcasts change
+ messages and saves/loads the list from a file.
+*/
+class JUCE_API PropertySet
+{
+public:
+ //==============================================================================
+ /** Creates an empty PropertySet.
+ @param ignoreCaseOfKeyNames if true, the names of properties are compared in a
+ case-insensitive way
+ */
+ PropertySet (bool ignoreCaseOfKeyNames = false);
+
+ /** Creates a copy of another PropertySet. */
+ PropertySet (const PropertySet& other);
+
+ /** Copies another PropertySet over this one. */
+ PropertySet& operator= (const PropertySet& other);
+
+ /** Destructor. */
+ virtual ~PropertySet();
+
+ //==============================================================================
+ /** Returns one of the properties as a string.
+
+ If the value isn't found in this set, then this will look for it in a fallback
+ property set (if you've specified one with the setFallbackPropertySet() method),
+ and if it can't find one there, it'll return the default value passed-in.
+
+ @param keyName the name of the property to retrieve
+ @param defaultReturnValue a value to return if the named property doesn't actually exist
+ */
+ String getValue (StringRef keyName, const String& defaultReturnValue = String()) const noexcept;
+
+ /** Returns one of the properties as an integer.
+
+ If the value isn't found in this set, then this will look for it in a fallback
+ property set (if you've specified one with the setFallbackPropertySet() method),
+ and if it can't find one there, it'll return the default value passed-in.
+
+ @param keyName the name of the property to retrieve
+ @param defaultReturnValue a value to return if the named property doesn't actually exist
+ */
+ int getIntValue (StringRef keyName, int defaultReturnValue = 0) const noexcept;
+
+ /** Returns one of the properties as an double.
+
+ If the value isn't found in this set, then this will look for it in a fallback
+ property set (if you've specified one with the setFallbackPropertySet() method),
+ and if it can't find one there, it'll return the default value passed-in.
+
+ @param keyName the name of the property to retrieve
+ @param defaultReturnValue a value to return if the named property doesn't actually exist
+ */
+ double getDoubleValue (StringRef keyName, double defaultReturnValue = 0.0) const noexcept;
+
+ /** Returns one of the properties as an boolean.
+
+ The result will be true if the string found for this key name can be parsed as a non-zero
+ integer.
+
+ If the value isn't found in this set, then this will look for it in a fallback
+ property set (if you've specified one with the setFallbackPropertySet() method),
+ and if it can't find one there, it'll return the default value passed-in.
+
+ @param keyName the name of the property to retrieve
+ @param defaultReturnValue a value to return if the named property doesn't actually exist
+ */
+ bool getBoolValue (StringRef keyName, bool defaultReturnValue = false) const noexcept;
+
+ /** Returns one of the properties as an XML element.
+
+ The result will a new XMLElement object that the caller must delete. If may return nullptr
+ if the key isn't found, or if the entry contains an string that isn't valid XML.
+
+ If the value isn't found in this set, then this will look for it in a fallback
+ property set (if you've specified one with the setFallbackPropertySet() method),
+ and if it can't find one there, it'll return the default value passed-in.
+
+ @param keyName the name of the property to retrieve
+ */
+ XmlElement* getXmlValue (StringRef keyName) const;
+
+ //==============================================================================
+ /** Sets a named property.
+
+ @param keyName the name of the property to set. (This mustn't be an empty string)
+ @param value the new value to set it to
+ */
+ void setValue (const String& keyName, const var& value);
+
+ /** Sets a named property to an XML element.
+
+ @param keyName the name of the property to set. (This mustn't be an empty string)
+ @param xml the new element to set it to. If this is zero, the value will be set to
+ an empty string
+ @see getXmlValue
+ */
+ void setValue (const String& keyName, const XmlElement* xml);
+
+ /** This copies all the values from a source PropertySet to this one.
+ This won't remove any existing settings, it just adds any that it finds in the source set.
+ */
+ void addAllPropertiesFrom (const PropertySet& source);
+
+ //==============================================================================
+ /** Deletes a property.
+ @param keyName the name of the property to delete. (This mustn't be an empty string)
+ */
+ void removeValue (StringRef keyName);
+
+ /** Returns true if the properies include the given key. */
+ bool containsKey (StringRef keyName) const noexcept;
+
+ /** Removes all values. */
+ void clear();
+
+ //==============================================================================
+ /** Returns the keys/value pair array containing all the properties. */
+ StringPairArray& getAllProperties() noexcept { return properties; }
+
+ /** Returns the lock used when reading or writing to this set */
+ const CriticalSection& getLock() const noexcept { return lock; }
+
+ //==============================================================================
+ /** Returns an XML element which encapsulates all the items in this property set.
+ The string parameter is the tag name that should be used for the node.
+ @see restoreFromXml
+ */
+ XmlElement* createXml (const String& nodeName) const;
+
+ /** Reloads a set of properties that were previously stored as XML.
+ The node passed in must have been created by the createXml() method.
+ @see createXml
+ */
+ void restoreFromXml (const XmlElement& xml);
+
+ //==============================================================================
+ /** Sets up a second PopertySet that will be used to look up any values that aren't
+ set in this one.
+
+ If you set this up to be a pointer to a second property set, then whenever one
+ of the getValue() methods fails to find an entry in this set, it will look up that
+ value in the fallback set, and if it finds it, it will return that.
+
+ Make sure that you don't delete the fallback set while it's still being used by
+ another set! To remove the fallback set, just call this method with a null pointer.
+
+ @see getFallbackPropertySet
+ */
+ void setFallbackPropertySet (PropertySet* fallbackProperties) noexcept;
+
+ /** Returns the fallback property set.
+ @see setFallbackPropertySet
+ */
+ PropertySet* getFallbackPropertySet() const noexcept { return fallbackProperties; }
+
+protected:
+ /** Subclasses can override this to be told when one of the properies has been changed. */
+ virtual void propertyChanged();
+
+private:
+ StringPairArray properties;
+ PropertySet* fallbackProperties;
+ CriticalSection lock;
+ bool ignoreCaseOfKeys;
+
+ JUCE_LEAK_DETECTOR (PropertySet)
+};
+
+
+#endif // JUCE_PROPERTYSET_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ReferenceCountedArray.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ReferenceCountedArray.h
new file mode 100644
index 0000000..d33343d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ReferenceCountedArray.h
@@ -0,0 +1,897 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
+#define JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Holds a list of objects derived from ReferenceCountedObject, or which implement basic
+ reference-count handling methods.
+
+ The template parameter specifies the class of the object you want to point to - the easiest
+ way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject
+ or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable
+ class by implementing a set of mathods called incReferenceCount(), decReferenceCount(), and
+ decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods
+ should behave.
+
+ A ReferenceCountedArray holds objects derived from ReferenceCountedObject,
+ and takes care of incrementing and decrementing their ref counts when they
+ are added and removed from the array.
+
+ To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
+ TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
+
+ @see Array, OwnedArray, StringArray
+*/
+template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
+class ReferenceCountedArray
+{
+public:
+ typedef ReferenceCountedObjectPtr<ObjectClass> ObjectClassPtr;
+
+ //==============================================================================
+ /** Creates an empty array.
+ @see ReferenceCountedObject, Array, OwnedArray
+ */
+ ReferenceCountedArray() noexcept
+ : numUsed (0)
+ {
+ }
+
+ /** Creates a copy of another array */
+ ReferenceCountedArray (const ReferenceCountedArray& other) noexcept
+ {
+ const ScopedLockType lock (other.getLock());
+ numUsed = other.size();
+ data.setAllocatedSize (numUsed);
+ memcpy (data.elements, other.getRawDataPointer(), (size_t) numUsed * sizeof (ObjectClass*));
+
+ for (int i = numUsed; --i >= 0;)
+ if (ObjectClass* o = data.elements[i])
+ o->incReferenceCount();
+ }
+
+ /** Creates a copy of another array */
+ template <class OtherObjectClass, class OtherCriticalSection>
+ ReferenceCountedArray (const ReferenceCountedArray<OtherObjectClass, OtherCriticalSection>& other) noexcept
+ {
+ const typename ReferenceCountedArray<OtherObjectClass, OtherCriticalSection>::ScopedLockType lock (other.getLock());
+ numUsed = other.size();
+ data.setAllocatedSize (numUsed);
+ memcpy (data.elements, other.getRawDataPointer(), numUsed * sizeof (ObjectClass*));
+
+ for (int i = numUsed; --i >= 0;)
+ if (ObjectClass* o = data.elements[i])
+ o->incReferenceCount();
+ }
+
+ /** Copies another array into this one.
+ Any existing objects in this array will first be released.
+ */
+ ReferenceCountedArray& operator= (const ReferenceCountedArray& other) noexcept
+ {
+ ReferenceCountedArray otherCopy (other);
+ swapWith (otherCopy);
+ return *this;
+ }
+
+ /** Copies another array into this one.
+ Any existing objects in this array will first be released.
+ */
+ template <class OtherObjectClass>
+ ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& operator= (const ReferenceCountedArray<OtherObjectClass, TypeOfCriticalSectionToUse>& other) noexcept
+ {
+ ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse> otherCopy (other);
+ swapWith (otherCopy);
+ return *this;
+ }
+
+ /** Destructor.
+ Any objects in the array will be released, and may be deleted if not referenced from elsewhere.
+ */
+ ~ReferenceCountedArray()
+ {
+ clear();
+ }
+
+ //==============================================================================
+ /** Removes all objects from the array.
+
+ Any objects in the array that are not referenced from elsewhere will be deleted.
+ */
+ void clear()
+ {
+ const ScopedLockType lock (getLock());
+
+ while (numUsed > 0)
+ if (ObjectClass* o = data.elements [--numUsed])
+ releaseObject (o);
+
+ jassert (numUsed == 0);
+ data.setAllocatedSize (0);
+ }
+
+ /** Returns the current number of objects in the array. */
+ inline int size() const noexcept
+ {
+ return numUsed;
+ }
+
+ /** Returns a pointer to the object at this index in the array.
+
+ If the index is out-of-range, this will return a null pointer, (and
+ it could be null anyway, because it's ok for the array to hold null
+ pointers as well as objects).
+
+ @see getUnchecked
+ */
+ inline ObjectClassPtr operator[] (const int index) const noexcept
+ {
+ return getObjectPointer (index);
+ }
+
+ /** Returns a pointer to the object at this index in the array, without checking
+ whether the index is in-range.
+
+ This is a faster and less safe version of operator[] which doesn't check the index passed in, so
+ it can be used when you're sure the index is always going to be legal.
+ */
+ inline ObjectClassPtr getUnchecked (const int index) const noexcept
+ {
+ return getObjectPointerUnchecked (index);
+ }
+
+ /** Returns a raw pointer to the object at this index in the array.
+
+ If the index is out-of-range, this will return a null pointer, (and
+ it could be null anyway, because it's ok for the array to hold null
+ pointers as well as objects).
+
+ @see getUnchecked
+ */
+ inline ObjectClass* getObjectPointer (const int index) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (index, numUsed))
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ return ObjectClassPtr();
+ }
+
+ /** Returns a raw pointer to the object at this index in the array, without checking
+ whether the index is in-range.
+ */
+ inline ObjectClass* getObjectPointerUnchecked (const int index) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
+ return data.elements [index];
+ }
+
+ /** Returns a pointer to the first object in the array.
+
+ This will return a null pointer if the array's empty.
+ @see getLast
+ */
+ inline ObjectClassPtr getFirst() const noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [0];
+ }
+
+ return ObjectClassPtr();
+ }
+
+ /** Returns a pointer to the last object in the array.
+
+ This will return a null pointer if the array's empty.
+ @see getFirst
+ */
+ inline ObjectClassPtr getLast() const noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (numUsed > 0)
+ {
+ jassert (data.elements != nullptr);
+ return data.elements [numUsed - 1];
+ }
+
+ return ObjectClassPtr();
+ }
+
+ /** Returns a pointer to the actual array data.
+ This pointer will only be valid until the next time a non-const method
+ is called on the array.
+ */
+ inline ObjectClass** getRawDataPointer() const noexcept
+ {
+ return data.elements;
+ }
+
+ //==============================================================================
+ /** Returns a pointer to the first element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ObjectClass** begin() const noexcept
+ {
+ return data.elements;
+ }
+
+ /** Returns a pointer to the element which follows the last element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ObjectClass** end() const noexcept
+ {
+ return data.elements + numUsed;
+ }
+
+ //==============================================================================
+ /** Finds the index of the first occurrence of an object in the array.
+
+ @param objectToLookFor the object to look for
+ @returns the index at which the object was found, or -1 if it's not found
+ */
+ int indexOf (const ObjectClass* const objectToLookFor) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ ObjectClass** e = data.elements.getData();
+ ObjectClass** const endPointer = e + numUsed;
+
+ while (e != endPointer)
+ {
+ if (objectToLookFor == *e)
+ return static_cast <int> (e - data.elements.getData());
+
+ ++e;
+ }
+
+ return -1;
+ }
+
+ /** Returns true if the array contains a specified object.
+
+ @param objectToLookFor the object to look for
+ @returns true if the object is in the array
+ */
+ bool contains (const ObjectClass* const objectToLookFor) const noexcept
+ {
+ const ScopedLockType lock (getLock());
+ ObjectClass** e = data.elements.getData();
+ ObjectClass** const endPointer = e + numUsed;
+
+ while (e != endPointer)
+ {
+ if (objectToLookFor == *e)
+ return true;
+
+ ++e;
+ }
+
+ return false;
+ }
+
+ /** Appends a new object to the end of the array.
+
+ This will increase the new object's reference count.
+
+ @param newObject the new object to add to the array
+ @see set, insert, addIfNotAlreadyThere, addSorted, addArray
+ */
+ ObjectClass* add (ObjectClass* const newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+ data.elements [numUsed++] = newObject;
+
+ if (newObject != nullptr)
+ newObject->incReferenceCount();
+
+ return newObject;
+ }
+
+ /** Inserts a new object into the array at the given index.
+
+ If the index is less than 0 or greater than the size of the array, the
+ element will be added to the end of the array.
+ Otherwise, it will be inserted into the array, moving all the later elements
+ along to make room.
+
+ This will increase the new object's reference count.
+
+ @param indexToInsertAt the index at which the new element should be inserted
+ @param newObject the new object to add to the array
+ @see add, addSorted, addIfNotAlreadyThere, set
+ */
+ ObjectClass* insert (int indexToInsertAt,
+ ObjectClass* const newObject) noexcept
+ {
+ if (indexToInsertAt < 0)
+ return add (newObject);
+
+ const ScopedLockType lock (getLock());
+
+ if (indexToInsertAt > numUsed)
+ indexToInsertAt = numUsed;
+
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+
+ ObjectClass** const e = data.elements + indexToInsertAt;
+ const int numToMove = numUsed - indexToInsertAt;
+
+ if (numToMove > 0)
+ memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
+
+ *e = newObject;
+
+ if (newObject != nullptr)
+ newObject->incReferenceCount();
+
+ ++numUsed;
+
+ return newObject;
+ }
+
+ /** Appends a new object at the end of the array as long as the array doesn't
+ already contain it.
+
+ If the array already contains a matching object, nothing will be done.
+
+ @param newObject the new object to add to the array
+ */
+ void addIfNotAlreadyThere (ObjectClass* const newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ if (! contains (newObject))
+ add (newObject);
+ }
+
+ /** Replaces an object in the array with a different one.
+
+ If the index is less than zero, this method does nothing.
+ If the index is beyond the end of the array, the new object is added to the end of the array.
+
+ The object being added has its reference count increased, and if it's replacing
+ another object, then that one has its reference count decreased, and may be deleted.
+
+ @param indexToChange the index whose value you want to change
+ @param newObject the new value to set for this index.
+ @see add, insert, remove
+ */
+ void set (const int indexToChange,
+ ObjectClass* const newObject)
+ {
+ if (indexToChange >= 0)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (newObject != nullptr)
+ newObject->incReferenceCount();
+
+ if (indexToChange < numUsed)
+ {
+ if (ObjectClass* o = data.elements [indexToChange])
+ releaseObject (o);
+
+ data.elements [indexToChange] = newObject;
+ }
+ else
+ {
+ data.ensureAllocatedSize (numUsed + 1);
+ jassert (data.elements != nullptr);
+ data.elements [numUsed++] = newObject;
+ }
+ }
+ }
+
+ /** Adds elements from another array to the end of this array.
+
+ @param arrayToAddFrom the array from which to copy the elements
+ @param startIndex the first element of the other array to start copying from
+ @param numElementsToAdd how many elements to add from the other array. If this
+ value is negative or greater than the number of available elements,
+ all available elements will be copied.
+ @see add
+ */
+ void addArray (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& arrayToAddFrom,
+ int startIndex = 0,
+ int numElementsToAdd = -1) noexcept
+ {
+ const ScopedLockType lock1 (arrayToAddFrom.getLock());
+
+ {
+ const ScopedLockType lock2 (getLock());
+
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
+ numElementsToAdd = arrayToAddFrom.size() - startIndex;
+
+ if (numElementsToAdd > 0)
+ {
+ data.ensureAllocatedSize (numUsed + numElementsToAdd);
+
+ while (--numElementsToAdd >= 0)
+ add (arrayToAddFrom.getUnchecked (startIndex++));
+ }
+ }
+ }
+
+ /** Inserts a new object into the array assuming that the array is sorted.
+
+ This will use a comparator to find the position at which the new object
+ should go. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator object to use to compare the elements - see the
+ sort() method for details about this object's form
+ @param newObject the new object to insert to the array
+ @returns the index at which the new object was added
+ @see add, sort
+ */
+ template <class ElementComparator>
+ int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
+ insert (index, newObject);
+ return index;
+ }
+
+ /** Inserts or replaces an object in the array, assuming it is sorted.
+
+ This is similar to addSorted, but if a matching element already exists, then it will be
+ replaced by the new one, rather than the new one being added as well.
+ */
+ template <class ElementComparator>
+ void addOrReplaceSorted (ElementComparator& comparator,
+ ObjectClass* newObject) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
+
+ if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0)
+ set (index - 1, newObject); // replace an existing object that matches
+ else
+ insert (index, newObject); // no match, so insert the new one
+ }
+
+ /** Finds the index of an object in the array, assuming that the array is sorted.
+
+ This will use a comparator to do a binary-chop to find the index of the given
+ element, if it exists. If the array isn't sorted, the behaviour of this
+ method will be unpredictable.
+
+ @param comparator the comparator to use to compare the elements - see the sort()
+ method for details about the form this object should take
+ @param objectToLookFor the object to search for
+ @returns the index of the element, or -1 if it's not found
+ @see addSorted, sort
+ */
+ template <class ElementComparator>
+ int indexOfSorted (ElementComparator& comparator,
+ const ObjectClass* const objectToLookFor) const noexcept
+ {
+ (void) comparator;
+ const ScopedLockType lock (getLock());
+ int s = 0, e = numUsed;
+
+ while (s < e)
+ {
+ if (comparator.compareElements (objectToLookFor, data.elements [s]) == 0)
+ return s;
+
+ const int halfway = (s + e) / 2;
+ if (halfway == s)
+ break;
+
+ if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
+ s = halfway;
+ else
+ e = halfway;
+ }
+
+ return -1;
+ }
+
+ //==============================================================================
+ /** Removes an object from the array.
+
+ This will remove the object at a given index and move back all the
+ subsequent objects to close the gap.
+
+ If the index passed in is out-of-range, nothing will happen.
+
+ The object that is removed will have its reference count decreased,
+ and may be deleted if not referenced from elsewhere.
+
+ @param indexToRemove the index of the element to remove
+ @see removeObject, removeRange
+ */
+ void remove (const int indexToRemove)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToRemove, numUsed))
+ {
+ ObjectClass** const e = data.elements + indexToRemove;
+
+ if (ObjectClass* o = *e)
+ releaseObject (o);
+
+ --numUsed;
+ const int numberToShift = numUsed - indexToRemove;
+
+ if (numberToShift > 0)
+ memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+ }
+
+ /** Removes and returns an object from the array.
+
+ This will remove the object at a given index and return it, moving back all
+ the subsequent objects to close the gap. If the index passed in is out-of-range,
+ nothing will happen and a null pointer will be returned.
+
+ @param indexToRemove the index of the element to remove
+ @see remove, removeObject, removeRange
+ */
+ ObjectClassPtr removeAndReturn (const int indexToRemove)
+ {
+ ObjectClassPtr removedItem;
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (indexToRemove, numUsed))
+ {
+ ObjectClass** const e = data.elements + indexToRemove;
+
+ if (ObjectClass* o = *e)
+ {
+ removedItem = o;
+ releaseObject (o);
+ }
+
+ --numUsed;
+ const int numberToShift = numUsed - indexToRemove;
+
+ if (numberToShift > 0)
+ memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+
+ return removedItem;
+ }
+
+ /** Removes the first occurrence of a specified object from the array.
+
+ If the item isn't found, no action is taken. If it is found, it is
+ removed and has its reference count decreased.
+
+ @param objectToRemove the object to try to remove
+ @see remove, removeRange
+ */
+ void removeObject (ObjectClass* const objectToRemove)
+ {
+ const ScopedLockType lock (getLock());
+ remove (indexOf (objectToRemove));
+ }
+
+ /** Removes a range of objects from the array.
+
+ This will remove a set of objects, starting from the given index,
+ and move any subsequent elements down to close the gap.
+
+ If the range extends beyond the bounds of the array, it will
+ be safely clipped to the size of the array.
+
+ The objects that are removed will have their reference counts decreased,
+ and may be deleted if not referenced from elsewhere.
+
+ @param startIndex the index of the first object to remove
+ @param numberToRemove how many objects should be removed
+ @see remove, removeObject
+ */
+ void removeRange (const int startIndex,
+ const int numberToRemove)
+ {
+ const ScopedLockType lock (getLock());
+
+ const int start = jlimit (0, numUsed, startIndex);
+ const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
+
+ if (endIndex > start)
+ {
+ int i;
+ for (i = start; i < endIndex; ++i)
+ {
+ if (ObjectClass* o = data.elements[i])
+ {
+ releaseObject (o);
+ data.elements[i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
+ }
+ }
+
+ const int rangeSize = endIndex - start;
+ ObjectClass** e = data.elements + start;
+ i = numUsed - endIndex;
+ numUsed -= rangeSize;
+
+ while (--i >= 0)
+ {
+ *e = e [rangeSize];
+ ++e;
+ }
+
+ if ((numUsed << 1) < data.numAllocated)
+ minimiseStorageOverheads();
+ }
+ }
+
+ /** Removes the last n objects from the array.
+
+ The objects that are removed will have their reference counts decreased,
+ and may be deleted if not referenced from elsewhere.
+
+ @param howManyToRemove how many objects to remove from the end of the array
+ @see remove, removeObject, removeRange
+ */
+ void removeLast (int howManyToRemove = 1)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (howManyToRemove > numUsed)
+ howManyToRemove = numUsed;
+
+ while (--howManyToRemove >= 0)
+ remove (numUsed - 1);
+ }
+
+ /** Swaps a pair of objects in the array.
+
+ If either of the indexes passed in is out-of-range, nothing will happen,
+ otherwise the two objects at these positions will be exchanged.
+ */
+ void swap (const int index1,
+ const int index2) noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (index1, numUsed)
+ && isPositiveAndBelow (index2, numUsed))
+ {
+ std::swap (data.elements [index1],
+ data.elements [index2]);
+ }
+ }
+
+ /** Moves one of the objects to a different position.
+
+ This will move the object to a specified index, shuffling along
+ any intervening elements as required.
+
+ So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
+ move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
+
+ @param currentIndex the index of the object to be moved. If this isn't a
+ valid index, then nothing will be done
+ @param newIndex the index at which you'd like this object to end up. If this
+ is less than zero, it will be moved to the end of the array
+ */
+ void move (const int currentIndex,
+ int newIndex) noexcept
+ {
+ if (currentIndex != newIndex)
+ {
+ const ScopedLockType lock (getLock());
+
+ if (isPositiveAndBelow (currentIndex, numUsed))
+ {
+ if (! isPositiveAndBelow (newIndex, numUsed))
+ newIndex = numUsed - 1;
+
+ ObjectClass* const value = data.elements [currentIndex];
+
+ if (newIndex > currentIndex)
+ {
+ memmove (data.elements + currentIndex,
+ data.elements + currentIndex + 1,
+ sizeof (ObjectClass*) * (size_t) (newIndex - currentIndex));
+ }
+ else
+ {
+ memmove (data.elements + newIndex + 1,
+ data.elements + newIndex,
+ sizeof (ObjectClass*) * (size_t) (currentIndex - newIndex));
+ }
+
+ data.elements [newIndex] = value;
+ }
+ }
+ }
+
+ //==============================================================================
+ /** This swaps the contents of this array with those of another array.
+
+ If you need to exchange two arrays, this is vastly quicker than using copy-by-value
+ because it just swaps their internal pointers.
+ */
+ template <class OtherArrayType>
+ void swapWith (OtherArrayType& otherArray) noexcept
+ {
+ const ScopedLockType lock1 (getLock());
+ const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
+ data.swapWith (otherArray.data);
+ std::swap (numUsed, otherArray.numUsed);
+ }
+
+ //==============================================================================
+ /** Compares this array to another one.
+
+ @returns true only if the other array contains the same objects in the same order
+ */
+ bool operator== (const ReferenceCountedArray& other) const noexcept
+ {
+ const ScopedLockType lock2 (other.getLock());
+ const ScopedLockType lock1 (getLock());
+
+ if (numUsed != other.numUsed)
+ return false;
+
+ for (int i = numUsed; --i >= 0;)
+ if (data.elements [i] != other.data.elements [i])
+ return false;
+
+ return true;
+ }
+
+ /** Compares this array to another one.
+
+ @see operator==
+ */
+ bool operator!= (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) const noexcept
+ {
+ return ! operator== (other);
+ }
+
+ //==============================================================================
+ /** Sorts the elements in the array.
+
+ This will use a comparator object to sort the elements into order. The object
+ passed must have a method of the form:
+ @code
+ int compareElements (ElementType first, ElementType second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator the comparator to use for comparing elements.
+ @param retainOrderOfEquivalentItems if this is true, then items
+ which the comparator says are equivalent will be
+ kept in the order in which they currently appear
+ in the array. This is slower to perform, but may
+ be important in some cases. If it's false, a faster
+ algorithm is used, but equivalent elements may be
+ rearranged.
+
+ @see sortArray
+ */
+ template <class ElementComparator>
+ void sort (ElementComparator& comparator,
+ const bool retainOrderOfEquivalentItems = false) const noexcept
+ {
+ (void) comparator; // if you pass in an object with a static compareElements() method, this
+ // avoids getting warning messages about the parameter being unused
+
+ const ScopedLockType lock (getLock());
+ sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
+ }
+
+ //==============================================================================
+ /** Reduces the amount of storage being used by the array.
+
+ Arrays typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads() noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.shrinkToNoMoreThan (numUsed);
+ }
+
+ /** Increases the array's internal storage to hold a minimum number of elements.
+
+ Calling this before adding a large known number of elements means that
+ the array won't have to keep dynamically resizing itself as the elements
+ are added, and it'll therefore be more efficient.
+ */
+ void ensureStorageAllocated (const int minNumElements)
+ {
+ const ScopedLockType lock (getLock());
+ data.ensureAllocatedSize (minNumElements);
+ }
+
+ //==============================================================================
+ /** Returns the CriticalSection that locks this array.
+ To lock, you can call getLock().enter() and getLock().exit(), or preferably use
+ an object of ScopedLockType as an RAII lock for it.
+ */
+ inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; }
+
+ /** Returns the type of scoped lock to use for locking this array */
+ typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
+
+
+ //==============================================================================
+ #ifndef DOXYGEN
+ // Note that the swapWithArray method has been replaced by a more flexible templated version,
+ // and renamed "swapWith" to be more consistent with the names used in other classes.
+ JUCE_DEPRECATED_WITH_BODY (void swapWithArray (ReferenceCountedArray& other) noexcept, { swapWith (other); })
+ #endif
+
+private:
+ //==============================================================================
+ ArrayAllocationBase <ObjectClass*, TypeOfCriticalSectionToUse> data;
+ int numUsed;
+
+ static void releaseObject (ObjectClass* o)
+ {
+ if (o->decReferenceCountWithoutDeleting())
+ ContainerDeletePolicy<ObjectClass>::destroy (o);
+ }
+};
+
+
+#endif // JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ScopedValueSetter.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ScopedValueSetter.h
new file mode 100644
index 0000000..13b871e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_ScopedValueSetter.h
@@ -0,0 +1,100 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SCOPEDVALUESETTER_H_INCLUDED
+#define JUCE_SCOPEDVALUESETTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Helper class providing an RAII-based mechanism for temporarily setting and
+ then re-setting a value.
+
+ E.g. @code
+ int x = 1;
+
+ {
+ ScopedValueSetter setter (x, 2);
+
+ // x is now 2
+ }
+
+ // x is now 1 again
+
+ {
+ ScopedValueSetter setter (x, 3, 4);
+
+ // x is now 3
+ }
+
+ // x is now 4
+ @endcode
+
+*/
+template <typename ValueType>
+class ScopedValueSetter
+{
+public:
+ /** Creates a ScopedValueSetter that will immediately change the specified value to the
+ given new value, and will then reset it to its original value when this object is deleted.
+ */
+ ScopedValueSetter (ValueType& valueToSet,
+ ValueType newValue)
+ : value (valueToSet),
+ originalValue (valueToSet)
+ {
+ valueToSet = newValue;
+ }
+
+ /** Creates a ScopedValueSetter that will immediately change the specified value to the
+ given new value, and will then reset it to be valueWhenDeleted when this object is deleted.
+ */
+ ScopedValueSetter (ValueType& valueToSet,
+ ValueType newValue,
+ ValueType valueWhenDeleted)
+ : value (valueToSet),
+ originalValue (valueWhenDeleted)
+ {
+ valueToSet = newValue;
+ }
+
+ ~ScopedValueSetter()
+ {
+ value = originalValue;
+ }
+
+private:
+ //==============================================================================
+ ValueType& value;
+ const ValueType originalValue;
+
+ JUCE_DECLARE_NON_COPYABLE (ScopedValueSetter)
+};
+
+
+#endif // JUCE_SCOPEDVALUESETTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SortedSet.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SortedSet.h
new file mode 100644
index 0000000..62fd923
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SortedSet.h
@@ -0,0 +1,494 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SORTEDSET_H_INCLUDED
+#define JUCE_SORTEDSET_H_INCLUDED
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4512)
+#endif
+
+//==============================================================================
+/**
+ Holds a set of unique primitive objects, such as ints or doubles.
+
+ A set can only hold one item with a given value, so if for example it's a
+ set of integers, attempting to add the same integer twice will do nothing
+ the second time.
+
+ Internally, the list of items is kept sorted (which means that whatever
+ kind of primitive type is used must support the ==, <, >, <= and >= operators
+ to determine the order), and searching the set for known values is very fast
+ because it uses a binary-chop method.
+
+ Note that if you're using a class or struct as the element type, it must be
+ capable of being copied or moved with a straightforward memcpy, rather than
+ needing construction and destruction code.
+
+ To make all the set's methods thread-safe, pass in "CriticalSection" as the templated
+ TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
+
+ @see Array, OwnedArray, ReferenceCountedArray, StringArray, CriticalSection
+*/
+template <class ElementType, class TypeOfCriticalSectionToUse = DummyCriticalSection>
+class SortedSet
+{
+public:
+ //==============================================================================
+ /** Creates an empty set. */
+ SortedSet() noexcept
+ {
+ }
+
+ /** Creates a copy of another set.
+ @param other the set to copy
+ */
+ SortedSet (const SortedSet& other)
+ : data (other.data)
+ {
+ }
+
+ /** Destructor. */
+ ~SortedSet() noexcept
+ {
+ }
+
+ /** Copies another set over this one.
+ @param other the set to copy
+ */
+ SortedSet& operator= (const SortedSet& other) noexcept
+ {
+ data = other.data;
+ return *this;
+ }
+
+ //==============================================================================
+ /** Compares this set to another one.
+ Two sets are considered equal if they both contain the same set of elements.
+ @param other the other set to compare with
+ */
+ bool operator== (const SortedSet<ElementType>& other) const noexcept
+ {
+ return data == other.data;
+ }
+
+ /** Compares this set to another one.
+ Two sets are considered equal if they both contain the same set of elements.
+ @param other the other set to compare with
+ */
+ bool operator!= (const SortedSet<ElementType>& other) const noexcept
+ {
+ return ! operator== (other);
+ }
+
+ //==============================================================================
+ /** Removes all elements from the set.
+
+ This will remove all the elements, and free any storage that the set is
+ using. To clear it without freeing the storage, use the clearQuick()
+ method instead.
+
+ @see clearQuick
+ */
+ void clear() noexcept
+ {
+ data.clear();
+ }
+
+ /** Removes all elements from the set without freeing the array's allocated storage.
+ @see clear
+ */
+ void clearQuick() noexcept
+ {
+ data.clearQuick();
+ }
+
+ //==============================================================================
+ /** Returns the current number of elements in the set. */
+ inline int size() const noexcept
+ {
+ return data.size();
+ }
+
+ /** Returns one of the elements in the set.
+
+ If the index passed in is beyond the range of valid elements, this
+ will return zero.
+
+ If you're certain that the index will always be a valid element, you
+ can call getUnchecked() instead, which is faster.
+
+ @param index the index of the element being requested (0 is the first element in the set)
+ @see getUnchecked, getFirst, getLast
+ */
+ inline ElementType operator[] (const int index) const noexcept
+ {
+ return data [index];
+ }
+
+ /** Returns one of the elements in the set, without checking the index passed in.
+ Unlike the operator[] method, this will try to return an element without
+ checking that the index is within the bounds of the set, so should only
+ be used when you're confident that it will always be a valid index.
+
+ @param index the index of the element being requested (0 is the first element in the set)
+ @see operator[], getFirst, getLast
+ */
+ inline ElementType getUnchecked (const int index) const noexcept
+ {
+ return data.getUnchecked (index);
+ }
+
+ /** Returns a direct reference to one of the elements in the set, without checking the index passed in.
+
+ This is like getUnchecked, but returns a direct reference to the element, so that
+ you can alter it directly. Obviously this can be dangerous, so only use it when
+ absolutely necessary.
+
+ @param index the index of the element being requested (0 is the first element in the array)
+ */
+ inline ElementType& getReference (const int index) const noexcept
+ {
+ return data.getReference (index);
+ }
+
+ /** Returns the first element in the set, or 0 if the set is empty.
+ @see operator[], getUnchecked, getLast
+ */
+ inline ElementType getFirst() const noexcept
+ {
+ return data.getFirst();
+ }
+
+ /** Returns the last element in the set, or 0 if the set is empty.
+ @see operator[], getUnchecked, getFirst
+ */
+ inline ElementType getLast() const noexcept
+ {
+ return data.getLast();
+ }
+
+ //==============================================================================
+ /** Returns a pointer to the first element in the set.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ElementType* begin() const noexcept
+ {
+ return data.begin();
+ }
+
+ /** Returns a pointer to the element which follows the last element in the set.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline ElementType* end() const noexcept
+ {
+ return data.end();
+ }
+
+ //==============================================================================
+ /** Finds the index of the first element which matches the value passed in.
+
+ This will search the set for the given object, and return the index
+ of its first occurrence. If the object isn't found, the method will return -1.
+
+ @param elementToLookFor the value or object to look for
+ @returns the index of the object, or -1 if it's not found
+ */
+ int indexOf (const ElementType& elementToLookFor) const noexcept
+ {
+ const ScopedLockType lock (data.getLock());
+
+ int s = 0;
+ int e = data.size();
+
+ for (;;)
+ {
+ if (s >= e)
+ return -1;
+
+ if (elementToLookFor == data.getReference (s))
+ return s;
+
+ const int halfway = (s + e) / 2;
+
+ if (halfway == s)
+ return -1;
+
+ if (elementToLookFor < data.getReference (halfway))
+ e = halfway;
+ else
+ s = halfway;
+ }
+ }
+
+ /** Returns true if the set contains at least one occurrence of an object.
+
+ @param elementToLookFor the value or object to look for
+ @returns true if the item is found
+ */
+ bool contains (const ElementType& elementToLookFor) const noexcept
+ {
+ return indexOf (elementToLookFor) >= 0;
+ }
+
+ //==============================================================================
+ /** Adds a new element to the set, (as long as it's not already in there).
+
+ Note that if a matching element already exists, the new value will be assigned
+ to the existing one using operator=, so that if there are any differences between
+ the objects which were not recognised by the object's operator==, then the
+ set will always contain a copy of the most recently added one.
+
+ @param newElement the new object to add to the set
+ @returns true if the value was added, or false if it already existed
+ @see set, insert, addIfNotAlreadyThere, addSorted, addSet, addArray
+ */
+ bool add (const ElementType& newElement) noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ int s = 0;
+ int e = data.size();
+
+ while (s < e)
+ {
+ ElementType& elem = data.getReference (s);
+ if (newElement == elem)
+ {
+ elem = newElement; // force an update in case operator== permits differences.
+ return false;
+ }
+
+ const int halfway = (s + e) / 2;
+ const bool isBeforeHalfway = (newElement < data.getReference (halfway));
+
+ if (halfway == s)
+ {
+ if (! isBeforeHalfway)
+ ++s;
+
+ break;
+ }
+
+ if (isBeforeHalfway)
+ e = halfway;
+ else
+ s = halfway;
+ }
+
+ data.insert (s, newElement);
+ return true;
+ }
+
+ /** Adds elements from an array to this set.
+
+ @param elementsToAdd the array of elements to add
+ @param numElementsToAdd how many elements are in this other array
+ @see add
+ */
+ void addArray (const ElementType* elementsToAdd,
+ int numElementsToAdd) noexcept
+ {
+ const ScopedLockType lock (getLock());
+
+ while (--numElementsToAdd >= 0)
+ add (*elementsToAdd++);
+ }
+
+ /** Adds elements from another set to this one.
+
+ @param setToAddFrom the set from which to copy the elements
+ @param startIndex the first element of the other set to start copying from
+ @param numElementsToAdd how many elements to add from the other set. If this
+ value is negative or greater than the number of available elements,
+ all available elements will be copied.
+ @see add
+ */
+ template <class OtherSetType>
+ void addSet (const OtherSetType& setToAddFrom,
+ int startIndex = 0,
+ int numElementsToAdd = -1) noexcept
+ {
+ const typename OtherSetType::ScopedLockType lock1 (setToAddFrom.getLock());
+
+ {
+ const ScopedLockType lock2 (getLock());
+ jassert (this != &setToAddFrom);
+
+ if (this != &setToAddFrom)
+ {
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > setToAddFrom.size())
+ numElementsToAdd = setToAddFrom.size() - startIndex;
+
+ if (numElementsToAdd > 0)
+ addArray (&setToAddFrom.data.getReference (startIndex), numElementsToAdd);
+ }
+ }
+ }
+
+ //==============================================================================
+ /** Removes an element from the set.
+
+ This will remove the element at a given index.
+ If the index passed in is out-of-range, nothing will happen.
+
+ @param indexToRemove the index of the element to remove
+ @returns the element that has been removed
+ @see removeValue, removeRange
+ */
+ ElementType remove (const int indexToRemove) noexcept
+ {
+ return data.remove (indexToRemove);
+ }
+
+ /** Removes an item from the set.
+
+ This will remove the given element from the set, if it's there.
+
+ @param valueToRemove the object to try to remove
+ @see remove, removeRange
+ */
+ void removeValue (const ElementType valueToRemove) noexcept
+ {
+ const ScopedLockType lock (getLock());
+ data.remove (indexOf (valueToRemove));
+ }
+
+ /** Removes any elements which are also in another set.
+
+ @param otherSet the other set in which to look for elements to remove
+ @see removeValuesNotIn, remove, removeValue, removeRange
+ */
+ template <class OtherSetType>
+ void removeValuesIn (const OtherSetType& otherSet) noexcept
+ {
+ const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (this == &otherSet)
+ {
+ clear();
+ }
+ else if (otherSet.size() > 0)
+ {
+ for (int i = data.size(); --i >= 0;)
+ if (otherSet.contains (data.getReference (i)))
+ remove (i);
+ }
+ }
+
+ /** Removes any elements which are not found in another set.
+
+ Only elements which occur in this other set will be retained.
+
+ @param otherSet the set in which to look for elements NOT to remove
+ @see removeValuesIn, remove, removeValue, removeRange
+ */
+ template <class OtherSetType>
+ void removeValuesNotIn (const OtherSetType& otherSet) noexcept
+ {
+ const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock());
+ const ScopedLockType lock2 (getLock());
+
+ if (this != &otherSet)
+ {
+ if (otherSet.size() <= 0)
+ {
+ clear();
+ }
+ else
+ {
+ for (int i = data.size(); --i >= 0;)
+ if (! otherSet.contains (data.getReference (i)))
+ remove (i);
+ }
+ }
+ }
+
+ /** This swaps the contents of this array with those of another array.
+
+ If you need to exchange two arrays, this is vastly quicker than using copy-by-value
+ because it just swaps their internal pointers.
+ */
+ template <class OtherSetType>
+ void swapWith (OtherSetType& otherSet) noexcept
+ {
+ data.swapWith (otherSet.data);
+ }
+
+ //==============================================================================
+ /** Reduces the amount of storage being used by the set.
+
+ Sets typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads() noexcept
+ {
+ data.minimiseStorageOverheads();
+ }
+
+ /** Increases the set's internal storage to hold a minimum number of elements.
+
+ Calling this before adding a large known number of elements means that
+ the set won't have to keep dynamically resizing itself as the elements
+ are added, and it'll therefore be more efficient.
+ */
+ void ensureStorageAllocated (const int minNumElements)
+ {
+ data.ensureStorageAllocated (minNumElements);
+ }
+
+ //==============================================================================
+ /** Returns the CriticalSection that locks this array.
+ To lock, you can call getLock().enter() and getLock().exit(), or preferably use
+ an object of ScopedLockType as an RAII lock for it.
+ */
+ inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data.getLock(); }
+
+ /** Returns the type of scoped lock to use for locking this array */
+ typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
+
+
+private:
+ //==============================================================================
+ Array<ElementType, TypeOfCriticalSectionToUse> data;
+};
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // JUCE_SORTEDSET_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SparseSet.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SparseSet.h
new file mode 100644
index 0000000..86366fc
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_SparseSet.h
@@ -0,0 +1,298 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SPARSESET_H_INCLUDED
+#define JUCE_SPARSESET_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Holds a set of primitive values, storing them as a set of ranges.
+
+ This container acts like an array, but can efficiently hold large contiguous
+ ranges of values. It's quite a specialised class, mostly useful for things
+ like keeping the set of selected rows in a listbox.
+
+ The type used as a template parameter must be an integer type, such as int, short,
+ int64, etc.
+*/
+template <class Type>
+class SparseSet
+{
+public:
+ //==============================================================================
+ /** Creates a new empty set. */
+ SparseSet()
+ {
+ }
+
+ /** Creates a copy of another SparseSet. */
+ SparseSet (const SparseSet<Type>& other)
+ : values (other.values)
+ {
+ }
+
+ //==============================================================================
+ /** Clears the set. */
+ void clear()
+ {
+ values.clear();
+ }
+
+ /** Checks whether the set is empty.
+
+ This is much quicker than using (size() == 0).
+ */
+ bool isEmpty() const noexcept
+ {
+ return values.size() == 0;
+ }
+
+ /** Returns the number of values in the set.
+
+ Because of the way the data is stored, this method can take longer if there
+ are a lot of items in the set. Use isEmpty() for a quick test of whether there
+ are any items.
+ */
+ Type size() const
+ {
+ Type total (0);
+
+ for (int i = 0; i < values.size(); i += 2)
+ total += values.getUnchecked (i + 1) - values.getUnchecked (i);
+
+ return total;
+ }
+
+ /** Returns one of the values in the set.
+
+ @param index the index of the value to retrieve, in the range 0 to (size() - 1).
+ @returns the value at this index, or 0 if it's out-of-range
+ */
+ Type operator[] (Type index) const
+ {
+ for (int i = 0; i < values.size(); i += 2)
+ {
+ const Type start (values.getUnchecked (i));
+ const Type len (values.getUnchecked (i + 1) - start);
+
+ if (index < len)
+ return start + index;
+
+ index -= len;
+ }
+
+ return Type();
+ }
+
+ /** Checks whether a particular value is in the set. */
+ bool contains (const Type valueToLookFor) const
+ {
+ for (int i = 0; i < values.size(); ++i)
+ if (valueToLookFor < values.getUnchecked(i))
+ return (i & 1) != 0;
+
+ return false;
+ }
+
+ //==============================================================================
+ /** Returns the number of contiguous blocks of values.
+ @see getRange
+ */
+ int getNumRanges() const noexcept
+ {
+ return values.size() >> 1;
+ }
+
+ /** Returns one of the contiguous ranges of values stored.
+ @param rangeIndex the index of the range to look up, between 0
+ and (getNumRanges() - 1)
+ @see getTotalRange
+ */
+ const Range<Type> getRange (const int rangeIndex) const
+ {
+ if (isPositiveAndBelow (rangeIndex, getNumRanges()))
+ return Range<Type> (values.getUnchecked (rangeIndex << 1),
+ values.getUnchecked ((rangeIndex << 1) + 1));
+
+ return Range<Type>();
+ }
+
+ /** Returns the range between the lowest and highest values in the set.
+ @see getRange
+ */
+ Range<Type> getTotalRange() const
+ {
+ if (values.size() > 0)
+ {
+ jassert ((values.size() & 1) == 0);
+ return Range<Type> (values.getUnchecked (0),
+ values.getUnchecked (values.size() - 1));
+ }
+
+ return Range<Type>();
+ }
+
+ //==============================================================================
+ /** Adds a range of contiguous values to the set.
+ e.g. addRange (Range \<int\> (10, 14)) will add (10, 11, 12, 13) to the set.
+ */
+ void addRange (const Range<Type> range)
+ {
+ jassert (range.getLength() >= 0);
+ if (range.getLength() > 0)
+ {
+ removeRange (range);
+
+ values.addUsingDefaultSort (range.getStart());
+ values.addUsingDefaultSort (range.getEnd());
+
+ simplify();
+ }
+ }
+
+ /** Removes a range of values from the set.
+ e.g. removeRange (Range\<int\> (10, 14)) will remove (10, 11, 12, 13) from the set.
+ */
+ void removeRange (const Range<Type> rangeToRemove)
+ {
+ jassert (rangeToRemove.getLength() >= 0);
+
+ if (rangeToRemove.getLength() > 0
+ && values.size() > 0
+ && rangeToRemove.getStart() < values.getUnchecked (values.size() - 1)
+ && values.getUnchecked(0) < rangeToRemove.getEnd())
+ {
+ const bool onAtStart = contains (rangeToRemove.getStart() - 1);
+ const Type lastValue (jmin (rangeToRemove.getEnd(), values.getLast()));
+ const bool onAtEnd = contains (lastValue);
+
+ for (int i = values.size(); --i >= 0;)
+ {
+ if (values.getUnchecked(i) <= lastValue)
+ {
+ while (values.getUnchecked(i) >= rangeToRemove.getStart())
+ {
+ values.remove (i);
+
+ if (--i < 0)
+ break;
+ }
+
+ break;
+ }
+ }
+
+ if (onAtStart) values.addUsingDefaultSort (rangeToRemove.getStart());
+ if (onAtEnd) values.addUsingDefaultSort (lastValue);
+
+ simplify();
+ }
+ }
+
+ /** Does an XOR of the values in a given range. */
+ void invertRange (const Range<Type> range)
+ {
+ SparseSet newItems;
+ newItems.addRange (range);
+
+ for (int i = getNumRanges(); --i >= 0;)
+ newItems.removeRange (getRange (i));
+
+ removeRange (range);
+
+ for (int i = newItems.getNumRanges(); --i >= 0;)
+ addRange (newItems.getRange(i));
+ }
+
+ /** Checks whether any part of a given range overlaps any part of this set. */
+ bool overlapsRange (const Range<Type> range)
+ {
+ if (range.getLength() > 0)
+ {
+ for (int i = getNumRanges(); --i >= 0;)
+ {
+ if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
+ return false;
+
+ if (values.getUnchecked (i << 1) < range.getEnd())
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Checks whether the whole of a given range is contained within this one. */
+ bool containsRange (const Range<Type> range)
+ {
+ if (range.getLength() > 0)
+ {
+ for (int i = getNumRanges(); --i >= 0;)
+ {
+ if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
+ return false;
+
+ if (values.getUnchecked (i << 1) <= range.getStart()
+ && range.getEnd() <= values.getUnchecked ((i << 1) + 1))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //==============================================================================
+ bool operator== (const SparseSet<Type>& other) noexcept
+ {
+ return values == other.values;
+ }
+
+ bool operator!= (const SparseSet<Type>& other) noexcept
+ {
+ return values != other.values;
+ }
+
+private:
+ //==============================================================================
+ // alternating start/end values of ranges of values that are present.
+ Array<Type, DummyCriticalSection> values;
+
+ void simplify()
+ {
+ jassert ((values.size() & 1) == 0);
+
+ for (int i = values.size(); --i > 0;)
+ if (values.getUnchecked(i) == values.getUnchecked (i - 1))
+ values.removeRange (--i, 2);
+ }
+};
+
+
+
+#endif // JUCE_SPARSESET_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.cpp
new file mode 100644
index 0000000..db3f2f5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.cpp
@@ -0,0 +1,780 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+enum VariantStreamMarkers
+{
+ varMarker_Int = 1,
+ varMarker_BoolTrue = 2,
+ varMarker_BoolFalse = 3,
+ varMarker_Double = 4,
+ varMarker_String = 5,
+ varMarker_Int64 = 6,
+ varMarker_Array = 7,
+ varMarker_Binary = 8,
+ varMarker_Undefined = 9
+};
+
+//==============================================================================
+class var::VariantType
+{
+public:
+ VariantType() noexcept {}
+ virtual ~VariantType() noexcept {}
+
+ virtual int toInt (const ValueUnion&) const noexcept { return 0; }
+ virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; }
+ virtual double toDouble (const ValueUnion&) const noexcept { return 0; }
+ virtual String toString (const ValueUnion&) const { return String::empty; }
+ virtual bool toBool (const ValueUnion&) const noexcept { return false; }
+ virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
+ virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; }
+ virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
+ virtual var clone (const var& original) const { return original; }
+
+ virtual bool isVoid() const noexcept { return false; }
+ virtual bool isUndefined() const noexcept { return false; }
+ virtual bool isInt() const noexcept { return false; }
+ virtual bool isInt64() const noexcept { return false; }
+ virtual bool isBool() const noexcept { return false; }
+ virtual bool isDouble() const noexcept { return false; }
+ virtual bool isString() const noexcept { return false; }
+ virtual bool isObject() const noexcept { return false; }
+ virtual bool isArray() const noexcept { return false; }
+ virtual bool isBinary() const noexcept { return false; }
+ virtual bool isMethod() const noexcept { return false; }
+
+ virtual void cleanUp (ValueUnion&) const noexcept {}
+ virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
+ virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
+ virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0;
+};
+
+//==============================================================================
+class var::VariantType_Void : public var::VariantType
+{
+public:
+ VariantType_Void() noexcept {}
+ static const VariantType_Void instance;
+
+ bool isVoid() const noexcept override { return true; }
+ bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
+ void writeToStream (const ValueUnion&, OutputStream& output) const override { output.writeCompressedInt (0); }
+};
+
+//==============================================================================
+class var::VariantType_Undefined : public var::VariantType
+{
+public:
+ VariantType_Undefined() noexcept {}
+ static const VariantType_Undefined instance;
+
+ bool isUndefined() const noexcept override { return true; }
+ String toString (const ValueUnion&) const override { return "undefined"; }
+ bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
+
+ void writeToStream (const ValueUnion&, OutputStream& output) const override
+ {
+ output.writeCompressedInt (1);
+ output.writeByte (varMarker_Undefined);
+ }
+};
+
+//==============================================================================
+class var::VariantType_Int : public var::VariantType
+{
+public:
+ VariantType_Int() noexcept {}
+ static const VariantType_Int instance;
+
+ int toInt (const ValueUnion& data) const noexcept override { return data.intValue; };
+ int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.intValue; };
+ double toDouble (const ValueUnion& data) const noexcept override { return (double) data.intValue; }
+ String toString (const ValueUnion& data) const override { return String (data.intValue); }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.intValue != 0; }
+ bool isInt() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ if (otherType.isDouble() || otherType.isInt64() || otherType.isString())
+ return otherType.equals (otherData, data, *this);
+
+ return otherType.toInt (otherData) == data.intValue;
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ output.writeCompressedInt (5);
+ output.writeByte (varMarker_Int);
+ output.writeInt (data.intValue);
+ }
+};
+
+//==============================================================================
+class var::VariantType_Int64 : public var::VariantType
+{
+public:
+ VariantType_Int64() noexcept {}
+ static const VariantType_Int64 instance;
+
+ int toInt (const ValueUnion& data) const noexcept override { return (int) data.int64Value; };
+ int64 toInt64 (const ValueUnion& data) const noexcept override { return data.int64Value; };
+ double toDouble (const ValueUnion& data) const noexcept override { return (double) data.int64Value; }
+ String toString (const ValueUnion& data) const override { return String (data.int64Value); }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.int64Value != 0; }
+ bool isInt64() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ if (otherType.isDouble() || otherType.isString())
+ return otherType.equals (otherData, data, *this);
+
+ return otherType.toInt64 (otherData) == data.int64Value;
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ output.writeCompressedInt (9);
+ output.writeByte (varMarker_Int64);
+ output.writeInt64 (data.int64Value);
+ }
+};
+
+//==============================================================================
+class var::VariantType_Double : public var::VariantType
+{
+public:
+ VariantType_Double() noexcept {}
+ static const VariantType_Double instance;
+
+ int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; };
+ int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; };
+ double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; }
+ String toString (const ValueUnion& data) const override { return String (data.doubleValue); }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0; }
+ bool isDouble() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ output.writeCompressedInt (9);
+ output.writeByte (varMarker_Double);
+ output.writeDouble (data.doubleValue);
+ }
+};
+
+//==============================================================================
+class var::VariantType_Bool : public var::VariantType
+{
+public:
+ VariantType_Bool() noexcept {}
+ static const VariantType_Bool instance;
+
+ int toInt (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
+ int64 toInt64 (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
+ double toDouble (const ValueUnion& data) const noexcept override { return data.boolValue ? 1.0 : 0.0; }
+ String toString (const ValueUnion& data) const override { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.boolValue; }
+ bool isBool() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ return otherType.toBool (otherData) == data.boolValue;
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ output.writeCompressedInt (1);
+ output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
+ }
+};
+
+//==============================================================================
+class var::VariantType_String : public var::VariantType
+{
+public:
+ VariantType_String() noexcept {}
+ static const VariantType_String instance;
+
+ void cleanUp (ValueUnion& data) const noexcept override { getString (data)-> ~String(); }
+ void createCopy (ValueUnion& dest, const ValueUnion& source) const override { new (dest.stringValue) String (*getString (source)); }
+
+ bool isString() const noexcept override { return true; }
+ int toInt (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue(); };
+ int64 toInt64 (const ValueUnion& data) const noexcept override { return getString (data)->getLargeIntValue(); };
+ double toDouble (const ValueUnion& data) const noexcept override { return getString (data)->getDoubleValue(); }
+ String toString (const ValueUnion& data) const override { return *getString (data); }
+ bool toBool (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue() != 0
+ || getString (data)->trim().equalsIgnoreCase ("true")
+ || getString (data)->trim().equalsIgnoreCase ("yes"); }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ return otherType.toString (otherData) == *getString (data);
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ const String* const s = getString (data);
+ const size_t len = s->getNumBytesAsUTF8() + 1;
+ HeapBlock<char> temp (len);
+ s->copyToUTF8 (temp, len);
+ output.writeCompressedInt ((int) (len + 1));
+ output.writeByte (varMarker_String);
+ output.write (temp, len);
+ }
+
+private:
+ static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast <const String*> (data.stringValue); }
+ static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast <String*> (data.stringValue); }
+};
+
+//==============================================================================
+class var::VariantType_Object : public var::VariantType
+{
+public:
+ VariantType_Object() noexcept {}
+ static const VariantType_Object instance;
+
+ void cleanUp (ValueUnion& data) const noexcept override { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
+
+ void createCopy (ValueUnion& dest, const ValueUnion& source) const override
+ {
+ dest.objectValue = source.objectValue;
+ if (dest.objectValue != nullptr)
+ dest.objectValue->incReferenceCount();
+ }
+
+ String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != 0; }
+ ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; }
+ bool isObject() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ return otherType.toObject (otherData) == data.objectValue;
+ }
+
+ var clone (const var& original) const override
+ {
+ if (DynamicObject* d = original.getDynamicObject())
+ return d->clone().get();
+
+ jassertfalse; // can only clone DynamicObjects!
+ return var();
+ }
+
+ void writeToStream (const ValueUnion&, OutputStream& output) const override
+ {
+ jassertfalse; // Can't write an object to a stream!
+ output.writeCompressedInt (0);
+ }
+};
+
+//==============================================================================
+class var::VariantType_Array : public var::VariantType_Object
+{
+public:
+ VariantType_Array() noexcept {}
+ static const VariantType_Array instance;
+
+ String toString (const ValueUnion&) const override { return "[Array]"; }
+ ReferenceCountedObject* toObject (const ValueUnion&) const noexcept override { return nullptr; }
+ bool isArray() const noexcept override { return true; }
+
+ Array<var>* toArray (const ValueUnion& data) const noexcept override
+ {
+ if (RefCountedArray* a = dynamic_cast<RefCountedArray*> (data.objectValue))
+ return &(a->array);
+
+ return nullptr;
+ }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ const Array<var>* const thisArray = toArray (data);
+ const Array<var>* const otherArray = otherType.toArray (otherData);
+ return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
+ }
+
+ var clone (const var& original) const override
+ {
+ Array<var> arrayCopy;
+
+ if (const Array<var>* array = toArray (original.value))
+ for (int i = 0; i < array->size(); ++i)
+ arrayCopy.add (array->getReference(i).clone());
+
+ return var (arrayCopy);
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ if (const Array<var>* array = toArray (data))
+ {
+ MemoryOutputStream buffer (512);
+ const int numItems = array->size();
+ buffer.writeCompressedInt (numItems);
+
+ for (int i = 0; i < numItems; ++i)
+ array->getReference(i).writeToStream (buffer);
+
+ output.writeCompressedInt (1 + (int) buffer.getDataSize());
+ output.writeByte (varMarker_Array);
+ output << buffer;
+ }
+ }
+
+ struct RefCountedArray : public ReferenceCountedObject
+ {
+ RefCountedArray (const Array<var>& a) : array (a) { incReferenceCount(); }
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ RefCountedArray (Array<var>&& a) : array (static_cast<Array<var>&&> (a)) { incReferenceCount(); }
+ #endif
+ Array<var> array;
+ };
+};
+
+//==============================================================================
+class var::VariantType_Binary : public var::VariantType
+{
+public:
+ VariantType_Binary() noexcept {}
+
+ static const VariantType_Binary instance;
+
+ void cleanUp (ValueUnion& data) const noexcept override { delete data.binaryValue; }
+ void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
+
+ String toString (const ValueUnion& data) const override { return data.binaryValue->toBase64Encoding(); }
+ bool isBinary() const noexcept override { return true; }
+ MemoryBlock* toBinary (const ValueUnion& data) const noexcept override { return data.binaryValue; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
+ return otherBlock != nullptr && *otherBlock == *data.binaryValue;
+ }
+
+ void writeToStream (const ValueUnion& data, OutputStream& output) const override
+ {
+ output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
+ output.writeByte (varMarker_Binary);
+ output << *data.binaryValue;
+ }
+};
+
+//==============================================================================
+class var::VariantType_Method : public var::VariantType
+{
+public:
+ VariantType_Method() noexcept {}
+ static const VariantType_Method instance;
+
+ String toString (const ValueUnion&) const override { return "Method"; }
+ bool toBool (const ValueUnion& data) const noexcept override { return data.methodValue != nullptr; }
+ bool isMethod() const noexcept override { return true; }
+
+ bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
+ {
+ return otherType.isMethod() && otherData.methodValue == data.methodValue;
+ }
+
+ void writeToStream (const ValueUnion&, OutputStream& output) const override
+ {
+ jassertfalse; // Can't write a method to a stream!
+ output.writeCompressedInt (0);
+ }
+};
+
+//==============================================================================
+const var::VariantType_Void var::VariantType_Void::instance;
+const var::VariantType_Undefined var::VariantType_Undefined::instance;
+const var::VariantType_Int var::VariantType_Int::instance;
+const var::VariantType_Int64 var::VariantType_Int64::instance;
+const var::VariantType_Bool var::VariantType_Bool::instance;
+const var::VariantType_Double var::VariantType_Double::instance;
+const var::VariantType_String var::VariantType_String::instance;
+const var::VariantType_Object var::VariantType_Object::instance;
+const var::VariantType_Array var::VariantType_Array::instance;
+const var::VariantType_Binary var::VariantType_Binary::instance;
+const var::VariantType_Method var::VariantType_Method::instance;
+
+
+//==============================================================================
+var::var() noexcept : type (&VariantType_Void::instance) {}
+var::var (const VariantType& t) noexcept : type (&t) {}
+var::~var() noexcept { type->cleanUp (value); }
+
+const var var::null;
+
+//==============================================================================
+var::var (const var& valueToCopy) : type (valueToCopy.type)
+{
+ type->createCopy (value, valueToCopy.value);
+}
+
+var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
+var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
+var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
+var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
+var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
+var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
+var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
+var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
+var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
+var::var (const void* v, size_t sz) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v, sz); }
+var::var (const MemoryBlock& v) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v); }
+
+var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
+{
+ value.objectValue = object;
+
+ if (object != nullptr)
+ object->incReferenceCount();
+}
+
+var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
+
+//==============================================================================
+bool var::isVoid() const noexcept { return type->isVoid(); }
+bool var::isUndefined() const noexcept { return type->isUndefined(); }
+bool var::isInt() const noexcept { return type->isInt(); }
+bool var::isInt64() const noexcept { return type->isInt64(); }
+bool var::isBool() const noexcept { return type->isBool(); }
+bool var::isDouble() const noexcept { return type->isDouble(); }
+bool var::isString() const noexcept { return type->isString(); }
+bool var::isObject() const noexcept { return type->isObject(); }
+bool var::isArray() const noexcept { return type->isArray(); }
+bool var::isBinaryData() const noexcept { return type->isBinary(); }
+bool var::isMethod() const noexcept { return type->isMethod(); }
+
+var::operator int() const noexcept { return type->toInt (value); }
+var::operator int64() const noexcept { return type->toInt64 (value); }
+var::operator bool() const noexcept { return type->toBool (value); }
+var::operator float() const noexcept { return (float) type->toDouble (value); }
+var::operator double() const noexcept { return type->toDouble (value); }
+String var::toString() const { return type->toString (value); }
+var::operator String() const { return type->toString (value); }
+ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
+Array<var>* var::getArray() const noexcept { return type->toArray (value); }
+MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); }
+DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast <DynamicObject*> (getObject()); }
+
+//==============================================================================
+void var::swapWith (var& other) noexcept
+{
+ std::swap (type, other.type);
+ std::swap (value, other.value);
+}
+
+var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
+var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
+var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
+var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
+var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
+var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
+var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
+var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
+var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
+var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
+var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+var::var (var&& other) noexcept
+ : type (other.type),
+ value (other.value)
+{
+ other.type = &VariantType_Void::instance;
+}
+
+var& var::operator= (var&& other) noexcept
+{
+ swapWith (other);
+ return *this;
+}
+
+var::var (String&& v) : type (&VariantType_String::instance)
+{
+ new (value.stringValue) String (static_cast<String&&> (v));
+}
+
+var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
+{
+ value.binaryValue = new MemoryBlock (static_cast<MemoryBlock&&> (v));
+}
+
+var::var (Array<var>&& v) : type (&VariantType_Array::instance)
+{
+ value.objectValue = new VariantType_Array::RefCountedArray (static_cast<Array<var>&&> (v));
+}
+
+var& var::operator= (String&& v)
+{
+ type->cleanUp (value);
+ type = &VariantType_String::instance;
+ new (value.stringValue) String (static_cast<String&&> (v));
+ return *this;
+}
+#endif
+
+//==============================================================================
+bool var::equals (const var& other) const noexcept
+{
+ return type->equals (value, other.value, *other.type);
+}
+
+bool var::equalsWithSameType (const var& other) const noexcept
+{
+ return type == other.type && equals (other);
+}
+
+bool var::hasSameTypeAs (const var& other) const noexcept
+{
+ return type == other.type;
+}
+
+bool operator== (const var& v1, const var& v2) noexcept { return v1.equals (v2); }
+bool operator!= (const var& v1, const var& v2) noexcept { return ! v1.equals (v2); }
+bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
+bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
+bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
+bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }
+
+//==============================================================================
+var var::clone() const noexcept
+{
+ return type->clone (*this);
+}
+
+//==============================================================================
+var var::operator[] (const Identifier propertyName) const
+{
+ if (DynamicObject* const o = getDynamicObject())
+ return o->getProperty (propertyName);
+
+ return var();
+}
+
+var var::operator[] (const char* const propertyName) const
+{
+ return operator[] (Identifier (propertyName));
+}
+
+var var::getProperty (const Identifier propertyName, const var& defaultReturnValue) const
+{
+ if (DynamicObject* const o = getDynamicObject())
+ return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
+
+ return defaultReturnValue;
+}
+
+var::NativeFunction var::getNativeFunction() const
+{
+ return isMethod() ? value.methodValue : nullptr;
+}
+
+var var::invoke (Identifier method, const var* arguments, int numArguments) const
+{
+ if (DynamicObject* const o = getDynamicObject())
+ return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments));
+
+ return var();
+}
+
+var var::call (const Identifier method) const
+{
+ return invoke (method, nullptr, 0);
+}
+
+var var::call (const Identifier method, const var& arg1) const
+{
+ return invoke (method, &arg1, 1);
+}
+
+var var::call (const Identifier method, const var& arg1, const var& arg2) const
+{
+ var args[] = { arg1, arg2 };
+ return invoke (method, args, 2);
+}
+
+var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3)
+{
+ var args[] = { arg1, arg2, arg3 };
+ return invoke (method, args, 3);
+}
+
+var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const
+{
+ var args[] = { arg1, arg2, arg3, arg4 };
+ return invoke (method, args, 4);
+}
+
+var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const
+{
+ var args[] = { arg1, arg2, arg3, arg4, arg5 };
+ return invoke (method, args, 5);
+}
+
+//==============================================================================
+int var::size() const
+{
+ if (const Array<var>* const array = getArray())
+ return array->size();
+
+ return 0;
+}
+
+const var& var::operator[] (int arrayIndex) const
+{
+ const Array<var>* const array = getArray();
+
+ // When using this method, the var must actually be an array, and the index
+ // must be in-range!
+ jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
+
+ return array->getReference (arrayIndex);
+}
+
+var& var::operator[] (int arrayIndex)
+{
+ const Array<var>* const array = getArray();
+
+ // When using this method, the var must actually be an array, and the index
+ // must be in-range!
+ jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
+
+ return array->getReference (arrayIndex);
+}
+
+Array<var>* var::convertToArray()
+{
+ if (Array<var>* array = getArray())
+ return array;
+
+ Array<var> tempVar;
+ if (! isVoid())
+ tempVar.add (*this);
+
+ *this = tempVar;
+ return getArray();
+}
+
+void var::append (const var& n)
+{
+ convertToArray()->add (n);
+}
+
+void var::remove (const int index)
+{
+ if (Array<var>* const array = getArray())
+ array->remove (index);
+}
+
+void var::insert (const int index, const var& n)
+{
+ convertToArray()->insert (index, n);
+}
+
+void var::resize (const int numArrayElementsWanted)
+{
+ convertToArray()->resize (numArrayElementsWanted);
+}
+
+int var::indexOf (const var& n) const
+{
+ if (const Array<var>* const array = getArray())
+ return array->indexOf (n);
+
+ return -1;
+}
+
+//==============================================================================
+void var::writeToStream (OutputStream& output) const
+{
+ type->writeToStream (value, output);
+}
+
+var var::readFromStream (InputStream& input)
+{
+ const int numBytes = input.readCompressedInt();
+
+ if (numBytes > 0)
+ {
+ switch (input.readByte())
+ {
+ case varMarker_Int: return var (input.readInt());
+ case varMarker_Int64: return var (input.readInt64());
+ case varMarker_BoolTrue: return var (true);
+ case varMarker_BoolFalse: return var (false);
+ case varMarker_Double: return var (input.readDouble());
+ case varMarker_String:
+ {
+ MemoryOutputStream mo;
+ mo.writeFromInputStream (input, numBytes - 1);
+ return var (mo.toUTF8());
+ }
+
+ case varMarker_Binary:
+ {
+ MemoryBlock mb ((size_t) numBytes - 1);
+
+ if (numBytes > 1)
+ {
+ const int numRead = input.read (mb.getData(), numBytes - 1);
+ mb.setSize ((size_t) numRead);
+ }
+
+ return var (mb);
+ }
+
+ case varMarker_Array:
+ {
+ var v;
+ Array<var>* const destArray = v.convertToArray();
+
+ for (int i = input.readCompressedInt(); --i >= 0;)
+ destArray->add (readFromStream (input));
+
+ return v;
+ }
+
+ default:
+ input.skipNextBytes (numBytes - 1); break;
+ }
+ }
+
+ return var();
+}
+
+var::NativeFunctionArgs::NativeFunctionArgs (const var& t, const var* args, int numArgs) noexcept
+ : thisObject (t), arguments (args), numArguments (numArgs)
+{}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.h b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.h
new file mode 100644
index 0000000..41a4884
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/containers/juce_Variant.h
@@ -0,0 +1,327 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_VARIANT_H_INCLUDED
+#define JUCE_VARIANT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A variant class, that can be used to hold a range of primitive values.
+
+ A var object can hold a range of simple primitive values, strings, or
+ any kind of ReferenceCountedObject. The var class is intended to act like
+ the kind of values used in dynamic scripting languages.
+
+ You can save/load var objects either in a small, proprietary binary format
+ using writeToStream()/readFromStream(), or as JSON by using the JSON class.
+
+ @see JSON, DynamicObject
+*/
+class JUCE_API var
+{
+public:
+ //==============================================================================
+ /** This structure is passed to a NativeFunction callback, and contains invocation
+ details about the function's arguments and context.
+ */
+ struct NativeFunctionArgs
+ {
+ NativeFunctionArgs (const var& thisObject, const var* args, int numArgs) noexcept;
+
+ const var& thisObject;
+ const var* arguments;
+ int numArguments;
+
+ JUCE_DECLARE_NON_COPYABLE (NativeFunctionArgs)
+ };
+
+ typedef var (*NativeFunction) (const NativeFunctionArgs&);
+ typedef Identifier identifier;
+
+ //==============================================================================
+ /** Creates a void variant. */
+ var() noexcept;
+
+ /** Destructor. */
+ ~var() noexcept;
+
+ /** A static var object that can be used where you need an empty variant object. */
+ static const var null;
+
+ var (const var& valueToCopy);
+ var (int value) noexcept;
+ var (int64 value) noexcept;
+ var (bool value) noexcept;
+ var (double value) noexcept;
+ var (const char* value);
+ var (const wchar_t* value);
+ var (const String& value);
+ var (const Array<var>& value);
+ var (ReferenceCountedObject* object);
+ var (NativeFunction method) noexcept;
+ var (const void* binaryData, size_t dataSize);
+ var (const MemoryBlock& binaryData);
+
+ var& operator= (const var& valueToCopy);
+ var& operator= (int value);
+ var& operator= (int64 value);
+ var& operator= (bool value);
+ var& operator= (double value);
+ var& operator= (const char* value);
+ var& operator= (const wchar_t* value);
+ var& operator= (const String& value);
+ var& operator= (const Array<var>& value);
+ var& operator= (ReferenceCountedObject* object);
+ var& operator= (NativeFunction method);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ var (var&& other) noexcept;
+ var (String&& value);
+ var (MemoryBlock&& binaryData);
+ var (Array<var>&& value);
+ var& operator= (var&& other) noexcept;
+ var& operator= (String&& value);
+ #endif
+
+ void swapWith (var& other) noexcept;
+
+ /** Returns a var object that can be used where you need the javascript "undefined" value. */
+ static var undefined() noexcept;
+
+ //==============================================================================
+ operator int() const noexcept;
+ operator int64() const noexcept;
+ operator bool() const noexcept;
+ operator float() const noexcept;
+ operator double() const noexcept;
+ operator String() const;
+ String toString() const;
+
+ /** If this variant holds an array, this provides access to it.
+ NOTE: Beware when you use this - the array pointer is only valid for the lifetime
+ of the variant that returned it, so be very careful not to call this method on temporary
+ var objects that are the return-value of a function, and which may go out of scope before
+ you use the array!
+ */
+ Array<var>* getArray() const noexcept;
+
+ /** If this variant holds a memory block, this provides access to it.
+ NOTE: Beware when you use this - the MemoryBlock pointer is only valid for the lifetime
+ of the variant that returned it, so be very careful not to call this method on temporary
+ var objects that are the return-value of a function, and which may go out of scope before
+ you use the MemoryBlock!
+ */
+ MemoryBlock* getBinaryData() const noexcept;
+
+ ReferenceCountedObject* getObject() const noexcept;
+ DynamicObject* getDynamicObject() const noexcept;
+
+ //==============================================================================
+ bool isVoid() const noexcept;
+ bool isUndefined() const noexcept;
+ bool isInt() const noexcept;
+ bool isInt64() const noexcept;
+ bool isBool() const noexcept;
+ bool isDouble() const noexcept;
+ bool isString() const noexcept;
+ bool isObject() const noexcept;
+ bool isArray() const noexcept;
+ bool isBinaryData() const noexcept;
+ bool isMethod() const noexcept;
+
+ /** Returns true if this var has the same value as the one supplied.
+ Note that this ignores the type, so a string var "123" and an integer var with the
+ value 123 are considered to be equal.
+ @see equalsWithSameType
+ */
+ bool equals (const var& other) const noexcept;
+
+ /** Returns true if this var has the same value and type as the one supplied.
+ This differs from equals() because e.g. "123" and 123 will be considered different.
+ @see equals
+ */
+ bool equalsWithSameType (const var& other) const noexcept;
+
+ /** Returns true if this var has the same type as the one supplied. */
+ bool hasSameTypeAs (const var& other) const noexcept;
+
+ /** Returns a deep copy of this object.
+ For simple types this just returns a copy, but if the object contains any arrays
+ or DynamicObjects, they will be cloned (recursively).
+ */
+ var clone() const noexcept;
+
+ //==============================================================================
+ /** If the var is an array, this returns the number of elements.
+ If the var isn't actually an array, this will return 0.
+ */
+ int size() const;
+
+ /** If the var is an array, this can be used to return one of its elements.
+ To call this method, you must make sure that the var is actually an array, and
+ that the index is a valid number. If these conditions aren't met, behaviour is
+ undefined.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ const var& operator[] (int arrayIndex) const;
+
+ /** If the var is an array, this can be used to return one of its elements.
+ To call this method, you must make sure that the var is actually an array, and
+ that the index is a valid number. If these conditions aren't met, behaviour is
+ undefined.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ var& operator[] (int arrayIndex);
+
+ /** Appends an element to the var, converting it to an array if it isn't already one.
+ If the var isn't an array, it will be converted to one, and if its value was non-void,
+ this value will be kept as the first element of the new array. The parameter value
+ will then be appended to it.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ void append (const var& valueToAppend);
+
+ /** Inserts an element to the var, converting it to an array if it isn't already one.
+ If the var isn't an array, it will be converted to one, and if its value was non-void,
+ this value will be kept as the first element of the new array. The parameter value
+ will then be inserted into it.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ void insert (int index, const var& value);
+
+ /** If the var is an array, this removes one of its elements.
+ If the index is out-of-range or the var isn't an array, nothing will be done.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ void remove (int index);
+
+ /** Treating the var as an array, this resizes it to contain the specified number of elements.
+ If the var isn't an array, it will be converted to one, and if its value was non-void,
+ this value will be kept as the first element of the new array before resizing.
+ For more control over the array's contents, you can call getArray() and manipulate
+ it directly as an Array\<var\>.
+ */
+ void resize (int numArrayElementsWanted);
+
+ /** If the var is an array, this searches it for the first occurrence of the specified value,
+ and returns its index.
+ If the var isn't an array, or if the value isn't found, this returns -1.
+ */
+ int indexOf (const var& value) const;
+
+ //==============================================================================
+ /** If this variant is an object, this returns one of its properties. */
+ var operator[] (Identifier propertyName) const;
+ /** If this variant is an object, this returns one of its properties. */
+ var operator[] (const char* propertyName) const;
+ /** If this variant is an object, this returns one of its properties, or a default
+ fallback value if the property is not set. */
+ var getProperty (Identifier propertyName, const var& defaultReturnValue) const;
+
+ /** Invokes a named method call with no arguments. */
+ var call (Identifier method) const;
+ /** Invokes a named method call with one argument. */
+ var call (Identifier method, const var& arg1) const;
+ /** Invokes a named method call with 2 arguments. */
+ var call (Identifier method, const var& arg1, const var& arg2) const;
+ /** Invokes a named method call with 3 arguments. */
+ var call (Identifier method, const var& arg1, const var& arg2, const var& arg3);
+ /** Invokes a named method call with 4 arguments. */
+ var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
+ /** Invokes a named method call with 5 arguments. */
+ var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
+ /** Invokes a named method call with a list of arguments. */
+ var invoke (Identifier method, const var* arguments, int numArguments) const;
+ /** If this object is a method, this returns the function pointer. */
+ NativeFunction getNativeFunction() const;
+
+ //==============================================================================
+ /** Writes a binary representation of this value to a stream.
+ The data can be read back later using readFromStream().
+ @see JSON
+ */
+ void writeToStream (OutputStream& output) const;
+
+ /** Reads back a stored binary representation of a value.
+ The data in the stream must have been written using writeToStream(), or this
+ will have unpredictable results.
+ @see JSON
+ */
+ static var readFromStream (InputStream& input);
+
+private:
+ //==============================================================================
+ class VariantType; friend class VariantType;
+ class VariantType_Void; friend class VariantType_Void;
+ class VariantType_Undefined; friend class VariantType_Undefined;
+ class VariantType_Int; friend class VariantType_Int;
+ class VariantType_Int64; friend class VariantType_Int64;
+ class VariantType_Double; friend class VariantType_Double;
+ class VariantType_Bool; friend class VariantType_Bool;
+ class VariantType_String; friend class VariantType_String;
+ class VariantType_Object; friend class VariantType_Object;
+ class VariantType_Array; friend class VariantType_Array;
+ class VariantType_Binary; friend class VariantType_Binary;
+ class VariantType_Method; friend class VariantType_Method;
+
+ union ValueUnion
+ {
+ int intValue;
+ int64 int64Value;
+ bool boolValue;
+ double doubleValue;
+ char stringValue [sizeof (String)];
+ ReferenceCountedObject* objectValue;
+ MemoryBlock* binaryValue;
+ NativeFunction methodValue;
+ };
+
+ const VariantType* type;
+ ValueUnion value;
+
+ Array<var>* convertToArray();
+ var (const VariantType&) noexcept;
+};
+
+/** Compares the values of two var objects, using the var::equals() comparison. */
+bool operator== (const var& v1, const var& v2) noexcept;
+/** Compares the values of two var objects, using the var::equals() comparison. */
+bool operator!= (const var& v1, const var& v2) noexcept;
+bool operator== (const var& v1, const String& v2);
+bool operator!= (const var& v1, const String& v2);
+bool operator== (const var& v1, const char* v2);
+bool operator!= (const var& v1, const char* v2);
+
+
+#endif // JUCE_VARIANT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.cpp
new file mode 100644
index 0000000..7d6dd4b
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.cpp
@@ -0,0 +1,159 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+DirectoryIterator::DirectoryIterator (const File& directory, bool recursive,
+ const String& pattern, const int type)
+ : wildCards (parseWildcards (pattern)),
+ fileFinder (directory, (recursive || wildCards.size() > 1) ? "*" : pattern),
+ wildCard (pattern),
+ path (File::addTrailingSeparator (directory.getFullPathName())),
+ index (-1),
+ totalNumFiles (-1),
+ whatToLookFor (type),
+ isRecursive (recursive),
+ hasBeenAdvanced (false)
+{
+ // you have to specify the type of files you're looking for!
+ jassert ((type & (File::findFiles | File::findDirectories)) != 0);
+ jassert (type > 0 && type <= 7);
+}
+
+DirectoryIterator::~DirectoryIterator()
+{
+}
+
+StringArray DirectoryIterator::parseWildcards (const String& pattern)
+{
+ StringArray s;
+ s.addTokens (pattern, ";,", "\"'");
+ s.trim();
+ s.removeEmptyStrings();
+ return s;
+}
+
+bool DirectoryIterator::fileMatches (const StringArray& wildCards, const String& filename)
+{
+ for (int i = 0; i < wildCards.size(); ++i)
+ if (filename.matchesWildcard (wildCards[i], ! File::areFileNamesCaseSensitive()))
+ return true;
+
+ return false;
+}
+
+bool DirectoryIterator::next()
+{
+ return next (nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+}
+
+bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ hasBeenAdvanced = true;
+
+ if (subIterator != nullptr)
+ {
+ if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly))
+ return true;
+
+ subIterator = nullptr;
+ }
+
+ String filename;
+ bool isDirectory, isHidden = false;
+
+ while (fileFinder.next (filename, &isDirectory,
+ (isHiddenResult != nullptr || (whatToLookFor & File::ignoreHiddenFiles) != 0) ? &isHidden : nullptr,
+ fileSize, modTime, creationTime, isReadOnly))
+ {
+ ++index;
+
+ if (! filename.containsOnly ("."))
+ {
+ bool matches = false;
+
+ if (isDirectory)
+ {
+ if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden))
+ subIterator = new DirectoryIterator (File::createFileWithoutCheckingPath (path + filename),
+ true, wildCard, whatToLookFor);
+
+ matches = (whatToLookFor & File::findDirectories) != 0;
+ }
+ else
+ {
+ matches = (whatToLookFor & File::findFiles) != 0;
+ }
+
+ // if we're not relying on the OS iterator to do the wildcard match, do it now..
+ if (matches && (isRecursive || wildCards.size() > 1))
+ matches = fileMatches (wildCards, filename);
+
+ if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0)
+ matches = ! isHidden;
+
+ if (matches)
+ {
+ currentFile = File::createFileWithoutCheckingPath (path + filename);
+ if (isHiddenResult != nullptr) *isHiddenResult = isHidden;
+ if (isDirResult != nullptr) *isDirResult = isDirectory;
+
+ return true;
+ }
+
+ if (subIterator != nullptr)
+ return next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly);
+ }
+ }
+
+ return false;
+}
+
+const File& DirectoryIterator::getFile() const
+{
+ if (subIterator != nullptr && subIterator->hasBeenAdvanced)
+ return subIterator->getFile();
+
+ // You need to call DirectoryIterator::next() before asking it for the file that it found!
+ jassert (hasBeenAdvanced);
+
+ return currentFile;
+}
+
+float DirectoryIterator::getEstimatedProgress() const
+{
+ if (totalNumFiles < 0)
+ totalNumFiles = File (path).getNumberOfChildFiles (File::findFilesAndDirectories);
+
+ if (totalNumFiles <= 0)
+ return 0.0f;
+
+ const float detailedIndex = (subIterator != nullptr) ? index + subIterator->getEstimatedProgress()
+ : (float) index;
+
+ return detailedIndex / totalNumFiles;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.h
new file mode 100644
index 0000000..3ca2265
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_DirectoryIterator.h
@@ -0,0 +1,159 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_DIRECTORYITERATOR_H_INCLUDED
+#define JUCE_DIRECTORYITERATOR_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Searches through the files in a directory, returning each file that is found.
+
+ A DirectoryIterator will search through a directory and its subdirectories using
+ a wildcard filepattern match.
+
+ If you may be scanning a large number of files, it's usually smarter to use this
+ class than File::findChildFiles() because it allows you to stop at any time, rather
+ than having to wait for the entire scan to finish before getting the results.
+
+ It also provides an estimate of its progress, using a (highly inaccurate!) algorithm.
+*/
+class JUCE_API DirectoryIterator
+{
+public:
+ //==============================================================================
+ /** Creates a DirectoryIterator for a given directory.
+
+ After creating one of these, call its next() method to get the
+ first file - e.g. @code
+
+ DirectoryIterator iter (File ("/animals/mooses"), true, "*.moose");
+
+ while (iter.next())
+ {
+ File theFileItFound (iter.getFile());
+
+ ... etc
+ }
+ @endcode
+
+ @param directory the directory to search in
+ @param isRecursive whether all the subdirectories should also be searched
+ @param wildCard the file pattern to match. This may contain multiple patterns
+ separated by a semi-colon or comma, e.g. "*.jpg;*.png"
+ @param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying
+ whether to look for files, directories, or both.
+ */
+ DirectoryIterator (const File& directory,
+ bool isRecursive,
+ const String& wildCard = "*",
+ int whatToLookFor = File::findFiles);
+
+ /** Destructor. */
+ ~DirectoryIterator();
+
+ /** Moves the iterator along to the next file.
+
+ @returns true if a file was found (you can then use getFile() to see what it was) - or
+ false if there are no more matching files.
+ */
+ bool next();
+
+ /** Moves the iterator along to the next file, and returns various properties of that file.
+
+ If you need to find out details about the file, it's more efficient to call this method than
+ to call the normal next() method and then find out the details afterwards.
+
+ All the parameters are optional, so pass null pointers for any items that you're not
+ interested in.
+
+ @returns true if a file was found (you can then use getFile() to see what it was) - or
+ false if there are no more matching files. If it returns false, then none of the
+ parameters will be filled-in.
+ */
+ bool next (bool* isDirectory,
+ bool* isHidden,
+ int64* fileSize,
+ Time* modTime,
+ Time* creationTime,
+ bool* isReadOnly);
+
+ /** Returns the file that the iterator is currently pointing at.
+
+ The result of this call is only valid after a call to next() has returned true.
+ */
+ const File& getFile() const;
+
+ /** Returns a guess of how far through the search the iterator has got.
+
+ @returns a value 0.0 to 1.0 to show the progress, although this won't be
+ very accurate.
+ */
+ float getEstimatedProgress() const;
+
+private:
+ //==============================================================================
+ class NativeIterator
+ {
+ public:
+ NativeIterator (const File& directory, const String& wildCard);
+ ~NativeIterator();
+
+ bool next (String& filenameFound,
+ bool* isDirectory, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly);
+
+ class Pimpl;
+
+ private:
+ friend class DirectoryIterator;
+ friend struct ContainerDeletePolicy<Pimpl>;
+ ScopedPointer<Pimpl> pimpl;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeIterator)
+ };
+
+ friend struct ContainerDeletePolicy<NativeIterator::Pimpl>;
+ StringArray wildCards;
+ NativeIterator fileFinder;
+ String wildCard, path;
+ int index;
+ mutable int totalNumFiles;
+ const int whatToLookFor;
+ const bool isRecursive;
+ bool hasBeenAdvanced;
+ ScopedPointer<DirectoryIterator> subIterator;
+ File currentFile;
+
+ static StringArray parseWildcards (const String& pattern);
+ static bool fileMatches (const StringArray& wildCards, const String& filename);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectoryIterator)
+};
+
+#endif // JUCE_DIRECTORYITERATOR_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.cpp
new file mode 100644
index 0000000..d5c520a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.cpp
@@ -0,0 +1,1086 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+File::File (const String& fullPathName)
+ : fullPath (parseAbsolutePath (fullPathName))
+{
+}
+
+File File::createFileWithoutCheckingPath (const String& path) noexcept
+{
+ File f;
+ f.fullPath = path;
+ return f;
+}
+
+File::File (const File& other)
+ : fullPath (other.fullPath)
+{
+}
+
+File& File::operator= (const String& newPath)
+{
+ fullPath = parseAbsolutePath (newPath);
+ return *this;
+}
+
+File& File::operator= (const File& other)
+{
+ fullPath = other.fullPath;
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+File::File (File&& other) noexcept
+ : fullPath (static_cast <String&&> (other.fullPath))
+{
+}
+
+File& File::operator= (File&& other) noexcept
+{
+ fullPath = static_cast <String&&> (other.fullPath);
+ return *this;
+}
+#endif
+
+const File File::nonexistent;
+
+
+//==============================================================================
+String File::parseAbsolutePath (const String& p)
+{
+ if (p.isEmpty())
+ return String();
+
+#if JUCE_WINDOWS
+ // Windows..
+ String path (p.replaceCharacter ('/', '\\'));
+
+ if (path.startsWithChar (separator))
+ {
+ if (path[1] != separator)
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse;
+
+ path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
+ }
+ }
+ else if (! path.containsChar (':'))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse;
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#else
+ // Mac or Linux..
+
+ // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
+ // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
+ // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
+ jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
+
+ String path (p);
+
+ if (path.startsWithChar ('~'))
+ {
+ if (path[1] == separator || path[1] == 0)
+ {
+ // expand a name of the form "~/abc"
+ path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
+ + path.substring (1);
+ }
+ else
+ {
+ // expand a name of type "~dave/abc"
+ const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
+
+ if (struct passwd* const pw = getpwnam (userName.toUTF8()))
+ path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
+ }
+ }
+ else if (! path.startsWithChar (separator))
+ {
+ #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
+ if (! (path.startsWith ("./") || path.startsWith ("../")))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse;
+
+ #if JUCE_LOG_ASSERTIONS
+ Logger::writeToLog ("Illegal absolute path: " + path);
+ #endif
+ }
+ #endif
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#endif
+
+ while (path.endsWithChar (separator) && path != separatorString) // careful not to turn a single "/" into an empty string.
+ path = path.dropLastCharacters (1);
+
+ return path;
+}
+
+String File::addTrailingSeparator (const String& path)
+{
+ return path.endsWithChar (separator) ? path
+ : path + separator;
+}
+
+//==============================================================================
+#if JUCE_LINUX
+ #define NAMES_ARE_CASE_SENSITIVE 1
+#endif
+
+bool File::areFileNamesCaseSensitive()
+{
+ #if NAMES_ARE_CASE_SENSITIVE
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+static int compareFilenames (const String& name1, const String& name2) noexcept
+{
+ #if NAMES_ARE_CASE_SENSITIVE
+ return name1.compare (name2);
+ #else
+ return name1.compareIgnoreCase (name2);
+ #endif
+}
+
+bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
+bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
+bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
+bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
+
+//==============================================================================
+bool File::setReadOnly (const bool shouldBeReadOnly,
+ const bool applyRecursively) const
+{
+ bool worked = true;
+
+ if (applyRecursively && isDirectory())
+ {
+ Array <File> subFiles;
+ findChildFiles (subFiles, File::findFilesAndDirectories, false);
+
+ for (int i = subFiles.size(); --i >= 0;)
+ worked = subFiles.getReference(i).setReadOnly (shouldBeReadOnly, true) && worked;
+ }
+
+ return setFileReadOnlyInternal (shouldBeReadOnly) && worked;
+}
+
+bool File::deleteRecursively() const
+{
+ bool worked = true;
+
+ if (isDirectory())
+ {
+ Array<File> subFiles;
+ findChildFiles (subFiles, File::findFilesAndDirectories, false);
+
+ for (int i = subFiles.size(); --i >= 0;)
+ worked = subFiles.getReference(i).deleteRecursively() && worked;
+ }
+
+ return deleteFile() && worked;
+}
+
+bool File::moveFileTo (const File& newFile) const
+{
+ if (newFile.fullPath == fullPath)
+ return true;
+
+ if (! exists())
+ return false;
+
+ #if ! NAMES_ARE_CASE_SENSITIVE
+ if (*this != newFile)
+ #endif
+ if (! newFile.deleteFile())
+ return false;
+
+ return moveInternal (newFile);
+}
+
+bool File::copyFileTo (const File& newFile) const
+{
+ return (*this == newFile)
+ || (exists() && newFile.deleteFile() && copyInternal (newFile));
+}
+
+bool File::copyDirectoryTo (const File& newDirectory) const
+{
+ if (isDirectory() && newDirectory.createDirectory())
+ {
+ Array<File> subFiles;
+ findChildFiles (subFiles, File::findFiles, false);
+
+ for (int i = 0; i < subFiles.size(); ++i)
+ if (! subFiles.getReference(i).copyFileTo (newDirectory.getChildFile (subFiles.getReference(i).getFileName())))
+ return false;
+
+ subFiles.clear();
+ findChildFiles (subFiles, File::findDirectories, false);
+
+ for (int i = 0; i < subFiles.size(); ++i)
+ if (! subFiles.getReference(i).copyDirectoryTo (newDirectory.getChildFile (subFiles.getReference(i).getFileName())))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+//==============================================================================
+String File::getPathUpToLastSlash() const
+{
+ const int lastSlash = fullPath.lastIndexOfChar (separator);
+
+ if (lastSlash > 0)
+ return fullPath.substring (0, lastSlash);
+
+ if (lastSlash == 0)
+ return separatorString;
+
+ return fullPath;
+}
+
+File File::getParentDirectory() const
+{
+ File f;
+ f.fullPath = getPathUpToLastSlash();
+ return f;
+}
+
+//==============================================================================
+String File::getFileName() const
+{
+ return fullPath.substring (fullPath.lastIndexOfChar (separator) + 1);
+}
+
+String File::getFileNameWithoutExtension() const
+{
+ const int lastSlash = fullPath.lastIndexOfChar (separator) + 1;
+ const int lastDot = fullPath.lastIndexOfChar ('.');
+
+ if (lastDot > lastSlash)
+ return fullPath.substring (lastSlash, lastDot);
+
+ return fullPath.substring (lastSlash);
+}
+
+bool File::isAChildOf (const File& potentialParent) const
+{
+ if (potentialParent.fullPath.isEmpty())
+ return false;
+
+ const String ourPath (getPathUpToLastSlash());
+
+ if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
+ return true;
+
+ if (potentialParent.fullPath.length() >= ourPath.length())
+ return false;
+
+ return getParentDirectory().isAChildOf (potentialParent);
+}
+
+int File::hashCode() const { return fullPath.hashCode(); }
+int64 File::hashCode64() const { return fullPath.hashCode64(); }
+
+//==============================================================================
+bool File::isAbsolutePath (StringRef path)
+{
+ return path.text[0] == separator
+ #if JUCE_WINDOWS
+ || (path.isNotEmpty() && path.text[1] == ':');
+ #else
+ || path.text[0] == '~';
+ #endif
+}
+
+File File::getChildFile (StringRef relativePath) const
+{
+ if (isAbsolutePath (relativePath))
+ return File (String (relativePath.text));
+
+ if (relativePath[0] != '.')
+ return File (addTrailingSeparator (fullPath) + relativePath);
+
+ String path (fullPath);
+
+ // It's relative, so remove any ../ or ./ bits at the start..
+ #if JUCE_WINDOWS
+ if (relativePath.text.indexOf ((juce_wchar) '/') >= 0)
+ return getChildFile (String (relativePath.text).replaceCharacter ('/', '\\'));
+ #endif
+
+ while (relativePath[0] == '.')
+ {
+ const juce_wchar secondChar = relativePath[1];
+
+ if (secondChar == '.')
+ {
+ const juce_wchar thirdChar = relativePath[2];
+
+ if (thirdChar == 0 || thirdChar == separator)
+ {
+ const int lastSlash = path.lastIndexOfChar (separator);
+ if (lastSlash >= 0)
+ path = path.substring (0, lastSlash);
+
+ relativePath = relativePath.text + (thirdChar == 0 ? 2 : 3);
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (secondChar == separator)
+ {
+ relativePath = relativePath.text + 2;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return File (addTrailingSeparator (path) + relativePath);
+}
+
+File File::getSiblingFile (StringRef fileName) const
+{
+ return getParentDirectory().getChildFile (fileName);
+}
+
+//==============================================================================
+String File::descriptionOfSizeInBytes (const int64 bytes)
+{
+ const char* suffix;
+ double divisor = 0;
+
+ if (bytes == 1) { suffix = " byte"; }
+ else if (bytes < 1024) { suffix = " bytes"; }
+ else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
+ else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
+ else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
+
+ return (divisor > 0 ? String (bytes / divisor, 1) : String (bytes)) + suffix;
+}
+
+//==============================================================================
+Result File::create() const
+{
+ if (exists())
+ return Result::ok();
+
+ const File parentDir (getParentDirectory());
+
+ if (parentDir == *this)
+ return Result::fail ("Cannot create parent directory");
+
+ Result r (parentDir.createDirectory());
+
+ if (r.wasOk())
+ {
+ FileOutputStream fo (*this, 8);
+ r = fo.getStatus();
+ }
+
+ return r;
+}
+
+Result File::createDirectory() const
+{
+ if (isDirectory())
+ return Result::ok();
+
+ const File parentDir (getParentDirectory());
+
+ if (parentDir == *this)
+ return Result::fail ("Cannot create parent directory");
+
+ Result r (parentDir.createDirectory());
+
+ if (r.wasOk())
+ r = createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString));
+
+ return r;
+}
+
+//==============================================================================
+Time File::getLastModificationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (m); }
+Time File::getLastAccessTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (a); }
+Time File::getCreationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (c); }
+
+bool File::setLastModificationTime (Time t) const { return setFileTimesInternal (t.toMilliseconds(), 0, 0); }
+bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); }
+bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); }
+
+//==============================================================================
+bool File::loadFileAsData (MemoryBlock& destBlock) const
+{
+ if (! existsAsFile())
+ return false;
+
+ FileInputStream in (*this);
+ return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock);
+}
+
+String File::loadFileAsString() const
+{
+ if (! existsAsFile())
+ return String();
+
+ FileInputStream in (*this);
+ return in.openedOk() ? in.readEntireStreamAsString()
+ : String();
+}
+
+void File::readLines (StringArray& destLines) const
+{
+ destLines.addLines (loadFileAsString());
+}
+
+//==============================================================================
+int File::findChildFiles (Array<File>& results,
+ const int whatToLookFor,
+ const bool searchRecursively,
+ const String& wildCardPattern) const
+{
+ int total = 0;
+
+ for (DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor); di.next();)
+ {
+ results.add (di.getFile());
+ ++total;
+ }
+
+ return total;
+}
+
+int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
+{
+ int total = 0;
+
+ for (DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor); di.next();)
+ ++total;
+
+ return total;
+}
+
+bool File::containsSubDirectories() const
+{
+ if (! isDirectory())
+ return false;
+
+ DirectoryIterator di (*this, false, "*", findDirectories);
+ return di.next();
+}
+
+//==============================================================================
+File File::getNonexistentChildFile (const String& suggestedPrefix,
+ const String& suffix,
+ bool putNumbersInBrackets) const
+{
+ File f (getChildFile (suggestedPrefix + suffix));
+
+ if (f.exists())
+ {
+ int number = 1;
+ String prefix (suggestedPrefix);
+
+ // remove any bracketed numbers that may already be on the end..
+ if (prefix.trim().endsWithChar (')'))
+ {
+ putNumbersInBrackets = true;
+
+ const int openBracks = prefix.lastIndexOfChar ('(');
+ const int closeBracks = prefix.lastIndexOfChar (')');
+
+ if (openBracks > 0
+ && closeBracks > openBracks
+ && prefix.substring (openBracks + 1, closeBracks).containsOnly ("0123456789"))
+ {
+ number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
+ prefix = prefix.substring (0, openBracks);
+ }
+ }
+
+ // also use brackets if it ends in a digit.
+ putNumbersInBrackets = putNumbersInBrackets
+ || CharacterFunctions::isDigit (prefix.getLastCharacter());
+
+ do
+ {
+ String newName (prefix);
+
+ if (putNumbersInBrackets)
+ newName << '(' << ++number << ')';
+ else
+ newName << ++number;
+
+ f = getChildFile (newName + suffix);
+
+ } while (f.exists());
+ }
+
+ return f;
+}
+
+File File::getNonexistentSibling (const bool putNumbersInBrackets) const
+{
+ if (! exists())
+ return *this;
+
+ return getParentDirectory().getNonexistentChildFile (getFileNameWithoutExtension(),
+ getFileExtension(),
+ putNumbersInBrackets);
+}
+
+//==============================================================================
+String File::getFileExtension() const
+{
+ const int indexOfDot = fullPath.lastIndexOfChar ('.');
+
+ if (indexOfDot > fullPath.lastIndexOfChar (separator))
+ return fullPath.substring (indexOfDot);
+
+ return String();
+}
+
+bool File::hasFileExtension (StringRef possibleSuffix) const
+{
+ if (possibleSuffix.isEmpty())
+ return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (separator);
+
+ const int semicolon = possibleSuffix.text.indexOf ((juce_wchar) ';');
+
+ if (semicolon >= 0)
+ return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
+ || hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
+
+ if (fullPath.endsWithIgnoreCase (possibleSuffix))
+ {
+ if (possibleSuffix.text[0] == '.')
+ return true;
+
+ const int dotPos = fullPath.length() - possibleSuffix.length() - 1;
+
+ if (dotPos >= 0)
+ return fullPath [dotPos] == '.';
+ }
+
+ return false;
+}
+
+File File::withFileExtension (StringRef newExtension) const
+{
+ if (fullPath.isEmpty())
+ return File();
+
+ String filePart (getFileName());
+
+ const int i = filePart.lastIndexOfChar ('.');
+ if (i >= 0)
+ filePart = filePart.substring (0, i);
+
+ if (newExtension.isNotEmpty() && newExtension.text[0] != '.')
+ filePart << '.';
+
+ return getSiblingFile (filePart + newExtension);
+}
+
+//==============================================================================
+bool File::startAsProcess (const String& parameters) const
+{
+ return exists() && Process::openDocument (fullPath, parameters);
+}
+
+//==============================================================================
+FileInputStream* File::createInputStream() const
+{
+ ScopedPointer<FileInputStream> fin (new FileInputStream (*this));
+
+ if (fin->openedOk())
+ return fin.release();
+
+ return nullptr;
+}
+
+FileOutputStream* File::createOutputStream (const size_t bufferSize) const
+{
+ ScopedPointer<FileOutputStream> out (new FileOutputStream (*this, bufferSize));
+
+ return out->failedToOpen() ? nullptr
+ : out.release();
+}
+
+//==============================================================================
+bool File::appendData (const void* const dataToAppend,
+ const size_t numberOfBytes) const
+{
+ jassert (((ssize_t) numberOfBytes) >= 0);
+
+ if (numberOfBytes == 0)
+ return true;
+
+ FileOutputStream out (*this, 8192);
+ return out.openedOk() && out.write (dataToAppend, numberOfBytes);
+}
+
+bool File::replaceWithData (const void* const dataToWrite,
+ const size_t numberOfBytes) const
+{
+ if (numberOfBytes == 0)
+ return deleteFile();
+
+ TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
+ tempFile.getFile().appendData (dataToWrite, numberOfBytes);
+ return tempFile.overwriteTargetFileWithTemporary();
+}
+
+bool File::appendText (const String& text,
+ const bool asUnicode,
+ const bool writeUnicodeHeaderBytes) const
+{
+ FileOutputStream out (*this);
+
+ if (out.failedToOpen())
+ return false;
+
+ out.writeText (text, asUnicode, writeUnicodeHeaderBytes);
+ return true;
+}
+
+bool File::replaceWithText (const String& textToWrite,
+ const bool asUnicode,
+ const bool writeUnicodeHeaderBytes) const
+{
+ TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
+ tempFile.getFile().appendText (textToWrite, asUnicode, writeUnicodeHeaderBytes);
+ return tempFile.overwriteTargetFileWithTemporary();
+}
+
+bool File::hasIdenticalContentTo (const File& other) const
+{
+ if (other == *this)
+ return true;
+
+ if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
+ {
+ FileInputStream in1 (*this), in2 (other);
+
+ if (in1.openedOk() && in2.openedOk())
+ {
+ const int bufferSize = 4096;
+ HeapBlock<char> buffer1 (bufferSize), buffer2 (bufferSize);
+
+ for (;;)
+ {
+ const int num1 = in1.read (buffer1, bufferSize);
+ const int num2 = in2.read (buffer2, bufferSize);
+
+ if (num1 != num2)
+ break;
+
+ if (num1 <= 0)
+ return true;
+
+ if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+//==============================================================================
+String File::createLegalPathName (const String& original)
+{
+ String s (original);
+ String start;
+
+ if (s.isNotEmpty() && s[1] == ':')
+ {
+ start = s.substring (0, 2);
+ s = s.substring (2);
+ }
+
+ return start + s.removeCharacters ("\"#@,;:<>*^|?")
+ .substring (0, 1024);
+}
+
+String File::createLegalFileName (const String& original)
+{
+ String s (original.removeCharacters ("\"#@,;:<>*^|?\\/"));
+
+ const int maxLength = 128; // only the length of the filename, not the whole path
+ const int len = s.length();
+
+ if (len > maxLength)
+ {
+ const int lastDot = s.lastIndexOfChar ('.');
+
+ if (lastDot > jmax (0, len - 12))
+ {
+ s = s.substring (0, maxLength - (len - lastDot))
+ + s.substring (lastDot);
+ }
+ else
+ {
+ s = s.substring (0, maxLength);
+ }
+ }
+
+ return s;
+}
+
+//==============================================================================
+static int countNumberOfSeparators (String::CharPointerType s)
+{
+ int num = 0;
+
+ for (;;)
+ {
+ const juce_wchar c = s.getAndAdvance();
+
+ if (c == 0)
+ break;
+
+ if (c == File::separator)
+ ++num;
+ }
+
+ return num;
+}
+
+String File::getRelativePathFrom (const File& dir) const
+{
+ String thisPath (fullPath);
+
+ while (thisPath.endsWithChar (separator))
+ thisPath = thisPath.dropLastCharacters (1);
+
+ String dirPath (addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
+ : dir.fullPath));
+
+ int commonBitLength = 0;
+ String::CharPointerType thisPathAfterCommon (thisPath.getCharPointer());
+ String::CharPointerType dirPathAfterCommon (dirPath.getCharPointer());
+
+ {
+ String::CharPointerType thisPathIter (thisPath.getCharPointer());
+ String::CharPointerType dirPathIter (dirPath.getCharPointer());
+
+ for (int i = 0;;)
+ {
+ const juce_wchar c1 = thisPathIter.getAndAdvance();
+ const juce_wchar c2 = dirPathIter.getAndAdvance();
+
+ #if NAMES_ARE_CASE_SENSITIVE
+ if (c1 != c2
+ #else
+ if ((c1 != c2 && CharacterFunctions::toLowerCase (c1) != CharacterFunctions::toLowerCase (c2))
+ #endif
+ || c1 == 0)
+ break;
+
+ ++i;
+
+ if (c1 == separator)
+ {
+ thisPathAfterCommon = thisPathIter;
+ dirPathAfterCommon = dirPathIter;
+ commonBitLength = i;
+ }
+ }
+ }
+
+ // if the only common bit is the root, then just return the full path..
+ if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] == separator))
+ return fullPath;
+
+ const int numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
+
+ if (numUpDirectoriesNeeded == 0)
+ return thisPathAfterCommon;
+
+ #if JUCE_WINDOWS
+ String s (String::repeatedString ("..\\", numUpDirectoriesNeeded));
+ #else
+ String s (String::repeatedString ("../", numUpDirectoriesNeeded));
+ #endif
+ s.appendCharPointer (thisPathAfterCommon);
+ return s;
+}
+
+//==============================================================================
+File File::createTempFile (StringRef fileNameEnding)
+{
+ const File tempFile (getSpecialLocation (tempDirectory)
+ .getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt()))
+ .withFileExtension (fileNameEnding));
+
+ if (tempFile.exists())
+ return createTempFile (fileNameEnding);
+
+ return tempFile;
+}
+
+//==============================================================================
+MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
+ : address (nullptr), range (0, file.getSize()), fileHandle (0)
+{
+ openInternal (file, mode);
+}
+
+MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRange, AccessMode mode)
+ : address (nullptr), range (fileRange.getIntersectionWith (Range<int64> (0, file.getSize()))), fileHandle (0)
+{
+ openInternal (file, mode);
+}
+
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class FileTests : public UnitTest
+{
+public:
+ FileTests() : UnitTest ("Files") {}
+
+ void runTest()
+ {
+ beginTest ("Reading");
+
+ const File home (File::getSpecialLocation (File::userHomeDirectory));
+ const File temp (File::getSpecialLocation (File::tempDirectory));
+
+ expect (! File::nonexistent.exists());
+ expect (home.isDirectory());
+ expect (home.exists());
+ expect (! home.existsAsFile());
+ expect (File::getSpecialLocation (File::userDocumentsDirectory).isDirectory());
+ expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory());
+ expect (File::getSpecialLocation (File::currentExecutableFile).exists());
+ expect (File::getSpecialLocation (File::currentApplicationFile).exists());
+ expect (File::getSpecialLocation (File::invokedExecutableFile).exists());
+ expect (home.getVolumeTotalSize() > 1024 * 1024);
+ expect (home.getBytesFreeOnVolume() > 0);
+ expect (! home.isHidden());
+ expect (home.isOnHardDisk());
+ expect (! home.isOnCDRomDrive());
+ expect (File::getCurrentWorkingDirectory().exists());
+ expect (home.setAsCurrentWorkingDirectory());
+ expect (File::getCurrentWorkingDirectory() == home);
+
+ {
+ Array<File> roots;
+ File::findFileSystemRoots (roots);
+ expect (roots.size() > 0);
+
+ int numRootsExisting = 0;
+ for (int i = 0; i < roots.size(); ++i)
+ if (roots[i].exists())
+ ++numRootsExisting;
+
+ // (on windows, some of the drives may not contain media, so as long as at least one is ok..)
+ expect (numRootsExisting > 0);
+ }
+
+ beginTest ("Writing");
+
+ File demoFolder (temp.getChildFile ("Juce UnitTests Temp Folder.folder"));
+ expect (demoFolder.deleteRecursively());
+ expect (demoFolder.createDirectory());
+ expect (demoFolder.isDirectory());
+ expect (demoFolder.getParentDirectory() == temp);
+ expect (temp.isDirectory());
+
+ {
+ Array<File> files;
+ temp.findChildFiles (files, File::findFilesAndDirectories, false, "*");
+ expect (files.contains (demoFolder));
+ }
+
+ {
+ Array<File> files;
+ temp.findChildFiles (files, File::findDirectories, true, "*.folder");
+ expect (files.contains (demoFolder));
+ }
+
+ File tempFile (demoFolder.getNonexistentChildFile ("test", ".txt", false));
+
+ expect (tempFile.getFileExtension() == ".txt");
+ expect (tempFile.hasFileExtension (".txt"));
+ expect (tempFile.hasFileExtension ("txt"));
+ expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz"));
+ expect (tempFile.withFileExtension ("xyz").hasFileExtension ("abc;xyz;foo"));
+ expect (tempFile.withFileExtension ("xyz").hasFileExtension ("xyz;foo"));
+ expect (! tempFile.withFileExtension ("h").hasFileExtension ("bar;foo;xx"));
+ expect (tempFile.getSiblingFile ("foo").isAChildOf (temp));
+ expect (tempFile.hasWriteAccess());
+
+ {
+ FileOutputStream fo (tempFile);
+ fo.write ("0123456789", 10);
+ }
+
+ expect (tempFile.exists());
+ expect (tempFile.getSize() == 10);
+ expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
+ expectEquals (tempFile.loadFileAsString(), String ("0123456789"));
+ expect (! demoFolder.containsSubDirectories());
+
+ expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName());
+ expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile), ".." + File::separatorString + ".." + File::separatorString + demoFolder.getParentDirectory().getFileName());
+
+ expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
+ expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
+ expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);
+ demoFolder.getNonexistentChildFile ("tempFolder", "", false).createDirectory();
+ expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 1);
+ expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 2);
+ expect (demoFolder.containsSubDirectories());
+
+ expect (tempFile.hasWriteAccess());
+ tempFile.setReadOnly (true);
+ expect (! tempFile.hasWriteAccess());
+ tempFile.setReadOnly (false);
+ expect (tempFile.hasWriteAccess());
+
+ Time t (Time::getCurrentTime());
+ tempFile.setLastModificationTime (t);
+ Time t2 = tempFile.getLastModificationTime();
+ expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
+
+ {
+ MemoryBlock mb;
+ tempFile.loadFileAsData (mb);
+ expect (mb.getSize() == 10);
+ expect (mb[0] == '0');
+ }
+
+ {
+ expect (tempFile.getSize() == 10);
+ FileOutputStream fo (tempFile);
+ expect (fo.openedOk());
+
+ expect (fo.setPosition (7));
+ expect (fo.truncate().wasOk());
+ expect (tempFile.getSize() == 7);
+ fo.write ("789", 3);
+ fo.flush();
+ expect (tempFile.getSize() == 10);
+ }
+
+ beginTest ("Memory-mapped files");
+
+ {
+ MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
+ expect (mmf.getSize() == 10);
+ expect (mmf.getData() != nullptr);
+ expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
+ }
+
+ {
+ const File tempFile2 (tempFile.getNonexistentSibling (false));
+ expect (tempFile2.create());
+ expect (tempFile2.appendData ("xxxxxxxxxx", 10));
+
+ {
+ MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
+ expect (mmf.getSize() == 10);
+ expect (mmf.getData() != nullptr);
+ memcpy (mmf.getData(), "abcdefghij", 10);
+ }
+
+ {
+ MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
+ expect (mmf.getSize() == 10);
+ expect (mmf.getData() != nullptr);
+ expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
+ }
+
+ expect (tempFile2.deleteFile());
+ }
+
+ beginTest ("More writing");
+
+ expect (tempFile.appendData ("abcdefghij", 10));
+ expect (tempFile.getSize() == 20);
+ expect (tempFile.replaceWithData ("abcdefghij", 10));
+ expect (tempFile.getSize() == 10);
+
+ File tempFile2 (tempFile.getNonexistentSibling (false));
+ expect (tempFile.copyFileTo (tempFile2));
+ expect (tempFile2.exists());
+ expect (tempFile2.hasIdenticalContentTo (tempFile));
+ expect (tempFile.deleteFile());
+ expect (! tempFile.exists());
+ expect (tempFile2.moveFileTo (tempFile));
+ expect (tempFile.exists());
+ expect (! tempFile2.exists());
+
+ expect (demoFolder.deleteRecursively());
+ expect (! demoFolder.exists());
+ }
+};
+
+static FileTests fileUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.h
new file mode 100644
index 0000000..57d970f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_File.h
@@ -0,0 +1,973 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILE_H_INCLUDED
+#define JUCE_FILE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a local file or directory.
+
+ This class encapsulates the absolute pathname of a file or directory, and
+ has methods for finding out about the file and changing its properties.
+
+ To read or write to the file, there are methods for returning an input or
+ output stream.
+
+ @see FileInputStream, FileOutputStream
+*/
+class JUCE_API File
+{
+public:
+ //==============================================================================
+ /** Creates an (invalid) file object.
+
+ The file is initially set to an empty path, so getFullPath() will return
+ an empty string, and comparing the file to File::nonexistent will return
+ true.
+
+ You can use its operator= method to point it at a proper file.
+ */
+ File() noexcept {}
+
+ /** Creates a file from an absolute path.
+
+ If the path supplied is a relative path, it is taken to be relative
+ to the current working directory (see File::getCurrentWorkingDirectory()),
+ but this isn't a recommended way of creating a file, because you
+ never know what the CWD is going to be.
+
+ On the Mac/Linux, the path can include "~" notation for referring to
+ user home directories.
+ */
+ File (const String& absolutePath);
+
+ /** Creates a copy of another file object. */
+ File (const File&);
+
+ /** Destructor. */
+ ~File() noexcept {}
+
+ /** Sets the file based on an absolute pathname.
+
+ If the path supplied is a relative path, it is taken to be relative
+ to the current working directory (see File::getCurrentWorkingDirectory()),
+ but this isn't a recommended way of creating a file, because you
+ never know what the CWD is going to be.
+
+ On the Mac/Linux, the path can include "~" notation for referring to
+ user home directories.
+ */
+ File& operator= (const String& newAbsolutePath);
+
+ /** Copies from another file object. */
+ File& operator= (const File& otherFile);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ File (File&&) noexcept;
+ File& operator= (File&&) noexcept;
+ #endif
+
+ //==============================================================================
+ /** This static constant is used for referring to an 'invalid' file. */
+ static const File nonexistent;
+
+ //==============================================================================
+ /** Checks whether the file actually exists.
+
+ @returns true if the file exists, either as a file or a directory.
+ @see existsAsFile, isDirectory
+ */
+ bool exists() const;
+
+ /** Checks whether the file exists and is a file rather than a directory.
+
+ @returns true only if this is a real file, false if it's a directory
+ or doesn't exist
+ @see exists, isDirectory
+ */
+ bool existsAsFile() const;
+
+ /** Checks whether the file is a directory that exists.
+
+ @returns true only if the file is a directory which actually exists, so
+ false if it's a file or doesn't exist at all
+ @see exists, existsAsFile
+ */
+ bool isDirectory() const;
+
+ /** Returns the size of the file in bytes.
+
+ @returns the number of bytes in the file, or 0 if it doesn't exist.
+ */
+ int64 getSize() const;
+
+ /** Utility function to convert a file size in bytes to a neat string description.
+
+ So for example 100 would return "100 bytes", 2000 would return "2 KB",
+ 2000000 would produce "2 MB", etc.
+ */
+ static String descriptionOfSizeInBytes (int64 bytes);
+
+ //==============================================================================
+ /** Returns the complete, absolute path of this file.
+
+ This includes the filename and all its parent folders. On Windows it'll
+ also include the drive letter prefix; on Mac or Linux it'll be a complete
+ path starting from the root folder.
+
+ If you just want the file's name, you should use getFileName() or
+ getFileNameWithoutExtension().
+
+ @see getFileName, getRelativePathFrom
+ */
+ const String& getFullPathName() const noexcept { return fullPath; }
+
+ /** Returns the last section of the pathname.
+
+ Returns just the final part of the path - e.g. if the whole path
+ is "/moose/fish/foo.txt" this will return "foo.txt".
+
+ For a directory, it returns the final part of the path - e.g. for the
+ directory "/moose/fish" it'll return "fish".
+
+ If the filename begins with a dot, it'll return the whole filename, e.g. for
+ "/moose/.fish", it'll return ".fish"
+
+ @see getFullPathName, getFileNameWithoutExtension
+ */
+ String getFileName() const;
+
+ /** Creates a relative path that refers to a file relatively to a given directory.
+
+ e.g. File ("/moose/foo.txt").getRelativePathFrom (File ("/moose/fish/haddock"))
+ would return "../../foo.txt".
+
+ If it's not possible to navigate from one file to the other, an absolute
+ path is returned. If the paths are invalid, an empty string may also be
+ returned.
+
+ @param directoryToBeRelativeTo the directory which the resultant string will
+ be relative to. If this is actually a file rather than
+ a directory, its parent directory will be used instead.
+ If it doesn't exist, it's assumed to be a directory.
+ @see getChildFile, isAbsolutePath
+ */
+ String getRelativePathFrom (const File& directoryToBeRelativeTo) const;
+
+ //==============================================================================
+ /** Returns the file's extension.
+
+ Returns the file extension of this file, also including the dot.
+
+ e.g. "/moose/fish/foo.txt" would return ".txt"
+
+ @see hasFileExtension, withFileExtension, getFileNameWithoutExtension
+ */
+ String getFileExtension() const;
+
+ /** Checks whether the file has a given extension.
+
+ @param extensionToTest the extension to look for - it doesn't matter whether or
+ not this string has a dot at the start, so ".wav" and "wav"
+ will have the same effect. To compare with multiple extensions, this
+ parameter can contain multiple strings, separated by semi-colons -
+ so, for example: hasFileExtension (".jpeg;png;gif") would return
+ true if the file has any of those three extensions.
+
+ @see getFileExtension, withFileExtension, getFileNameWithoutExtension
+ */
+ bool hasFileExtension (StringRef extensionToTest) const;
+
+ /** Returns a version of this file with a different file extension.
+
+ e.g. File ("/moose/fish/foo.txt").withFileExtension ("html") returns "/moose/fish/foo.html"
+
+ @param newExtension the new extension, either with or without a dot at the start (this
+ doesn't make any difference). To get remove a file's extension altogether,
+ pass an empty string into this function.
+
+ @see getFileName, getFileExtension, hasFileExtension, getFileNameWithoutExtension
+ */
+ File withFileExtension (StringRef newExtension) const;
+
+ /** Returns the last part of the filename, without its file extension.
+
+ e.g. for "/moose/fish/foo.txt" this will return "foo".
+
+ @see getFileName, getFileExtension, hasFileExtension, withFileExtension
+ */
+ String getFileNameWithoutExtension() const;
+
+ //==============================================================================
+ /** Returns a 32-bit hash-code that identifies this file.
+
+ This is based on the filename. Obviously it's possible, although unlikely, that
+ two files will have the same hash-code.
+ */
+ int hashCode() const;
+
+ /** Returns a 64-bit hash-code that identifies this file.
+
+ This is based on the filename. Obviously it's possible, although unlikely, that
+ two files will have the same hash-code.
+ */
+ int64 hashCode64() const;
+
+ //==============================================================================
+ /** Returns a file that represents a relative (or absolute) sub-path of the current one.
+
+ This will find a child file or directory of the current object.
+
+ e.g.
+ File ("/moose/fish").getChildFile ("foo.txt") will produce "/moose/fish/foo.txt".
+ File ("/moose/fish").getChildFile ("haddock/foo.txt") will produce "/moose/fish/haddock/foo.txt".
+ File ("/moose/fish").getChildFile ("../foo.txt") will produce "/moose/foo.txt".
+
+ If the string is actually an absolute path, it will be treated as such, e.g.
+ File ("/moose/fish").getChildFile ("/foo.txt") will produce "/foo.txt"
+
+ @see getSiblingFile, getParentDirectory, getRelativePathFrom, isAChildOf
+ */
+ File getChildFile (StringRef relativeOrAbsolutePath) const;
+
+ /** Returns a file which is in the same directory as this one.
+
+ This is equivalent to getParentDirectory().getChildFile (name).
+
+ @see getChildFile, getParentDirectory
+ */
+ File getSiblingFile (StringRef siblingFileName) const;
+
+ //==============================================================================
+ /** Returns the directory that contains this file or directory.
+
+ e.g. for "/moose/fish/foo.txt" this will return "/moose/fish".
+ */
+ File getParentDirectory() const;
+
+ /** Checks whether a file is somewhere inside a directory.
+
+ Returns true if this file is somewhere inside a subdirectory of the directory
+ that is passed in. Neither file actually has to exist, because the function
+ just checks the paths for similarities.
+
+ e.g. File ("/moose/fish/foo.txt").isAChildOf ("/moose") is true.
+ File ("/moose/fish/foo.txt").isAChildOf ("/moose/fish") is also true.
+ */
+ bool isAChildOf (const File& potentialParentDirectory) const;
+
+ //==============================================================================
+ /** Chooses a filename relative to this one that doesn't already exist.
+
+ If this file is a directory, this will return a child file of this
+ directory that doesn't exist, by adding numbers to a prefix and suffix until
+ it finds one that isn't already there.
+
+ If the prefix + the suffix doesn't exist, it won't bother adding a number.
+
+ e.g. File ("/moose/fish").getNonexistentChildFile ("foo", ".txt", true) might
+ return "/moose/fish/foo(2).txt" if there's already a file called "foo.txt".
+
+ @param prefix the string to use for the filename before the number
+ @param suffix the string to add to the filename after the number
+ @param putNumbersInBrackets if true, this will create filenames in the
+ format "prefix(number)suffix", if false, it will leave the
+ brackets out.
+ */
+ File getNonexistentChildFile (const String& prefix,
+ const String& suffix,
+ bool putNumbersInBrackets = true) const;
+
+ /** Chooses a filename for a sibling file to this one that doesn't already exist.
+
+ If this file doesn't exist, this will just return itself, otherwise it
+ will return an appropriate sibling that doesn't exist, e.g. if a file
+ "/moose/fish/foo.txt" exists, this might return "/moose/fish/foo(2).txt".
+
+ @param putNumbersInBrackets whether to add brackets around the numbers that
+ get appended to the new filename.
+ */
+ File getNonexistentSibling (bool putNumbersInBrackets = true) const;
+
+ //==============================================================================
+ /** Compares the pathnames for two files. */
+ bool operator== (const File&) const;
+ /** Compares the pathnames for two files. */
+ bool operator!= (const File&) const;
+ /** Compares the pathnames for two files. */
+ bool operator< (const File&) const;
+ /** Compares the pathnames for two files. */
+ bool operator> (const File&) const;
+
+ //==============================================================================
+ /** Checks whether a file can be created or written to.
+
+ @returns true if it's possible to create and write to this file. If the file
+ doesn't already exist, this will check its parent directory to
+ see if writing is allowed.
+ @see setReadOnly
+ */
+ bool hasWriteAccess() const;
+
+ /** Changes the write-permission of a file or directory.
+
+ @param shouldBeReadOnly whether to add or remove write-permission
+ @param applyRecursively if the file is a directory and this is true, it will
+ recurse through all the subfolders changing the permissions
+ of all files
+ @returns true if it manages to change the file's permissions.
+ @see hasWriteAccess
+ */
+ bool setReadOnly (bool shouldBeReadOnly,
+ bool applyRecursively = false) const;
+
+ /** Returns true if this file is a hidden or system file.
+ The criteria for deciding whether a file is hidden are platform-dependent.
+ */
+ bool isHidden() const;
+
+ /** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */
+ bool isLink() const;
+
+ /** If this file is a link or alias, this returns the file that it points to.
+ If the file isn't actually link, it'll just return itself.
+ */
+ File getLinkedTarget() const;
+
+ /** Returns a unique identifier for the file, if one is available.
+
+ Depending on the OS and file-system, this may be a unix inode number or
+ a win32 file identifier, or 0 if it fails to find one. The number will
+ be unique on the filesystem, but not globally.
+ */
+ uint64 getFileIdentifier() const;
+
+ //==============================================================================
+ /** Returns the last modification time of this file.
+
+ @returns the time, or an invalid time if the file doesn't exist.
+ @see setLastModificationTime, getLastAccessTime, getCreationTime
+ */
+ Time getLastModificationTime() const;
+
+ /** Returns the last time this file was accessed.
+
+ @returns the time, or an invalid time if the file doesn't exist.
+ @see setLastAccessTime, getLastModificationTime, getCreationTime
+ */
+ Time getLastAccessTime() const;
+
+ /** Returns the time that this file was created.
+
+ @returns the time, or an invalid time if the file doesn't exist.
+ @see getLastModificationTime, getLastAccessTime
+ */
+ Time getCreationTime() const;
+
+ /** Changes the modification time for this file.
+
+ @param newTime the time to apply to the file
+ @returns true if it manages to change the file's time.
+ @see getLastModificationTime, setLastAccessTime, setCreationTime
+ */
+ bool setLastModificationTime (Time newTime) const;
+
+ /** Changes the last-access time for this file.
+
+ @param newTime the time to apply to the file
+ @returns true if it manages to change the file's time.
+ @see getLastAccessTime, setLastModificationTime, setCreationTime
+ */
+ bool setLastAccessTime (Time newTime) const;
+
+ /** Changes the creation date for this file.
+
+ @param newTime the time to apply to the file
+ @returns true if it manages to change the file's time.
+ @see getCreationTime, setLastModificationTime, setLastAccessTime
+ */
+ bool setCreationTime (Time newTime) const;
+
+ /** If possible, this will try to create a version string for the given file.
+
+ The OS may be able to look at the file and give a version for it - e.g. with
+ executables, bundles, dlls, etc. If no version is available, this will
+ return an empty string.
+ */
+ String getVersion() const;
+
+ //==============================================================================
+ /** Creates an empty file if it doesn't already exist.
+
+ If the file that this object refers to doesn't exist, this will create a file
+ of zero size.
+
+ If it already exists or is a directory, this method will do nothing.
+
+ @returns true if the file has been created (or if it already existed).
+ @see createDirectory
+ */
+ Result create() const;
+
+ /** Creates a new directory for this filename.
+
+ This will try to create the file as a directory, and fill also create
+ any parent directories it needs in order to complete the operation.
+
+ @returns a result to indicate whether the directory was created successfully, or
+ an error message if it failed.
+ @see create
+ */
+ Result createDirectory() const;
+
+ /** Deletes a file.
+
+ If this file is actually a directory, it may not be deleted correctly if it
+ contains files. See deleteRecursively() as a better way of deleting directories.
+
+ @returns true if the file has been successfully deleted (or if it didn't exist to
+ begin with).
+ @see deleteRecursively
+ */
+ bool deleteFile() const;
+
+ /** Deletes a file or directory and all its subdirectories.
+
+ If this file is a directory, this will try to delete it and all its subfolders. If
+ it's just a file, it will just try to delete the file.
+
+ @returns true if the file and all its subfolders have been successfully deleted
+ (or if it didn't exist to begin with).
+ @see deleteFile
+ */
+ bool deleteRecursively() const;
+
+ /** Moves this file or folder to the trash.
+
+ @returns true if the operation succeeded. It could fail if the trash is full, or
+ if the file is write-protected, so you should check the return value
+ and act appropriately.
+ */
+ bool moveToTrash() const;
+
+ /** Moves or renames a file.
+
+ Tries to move a file to a different location.
+ If the target file already exists, this will attempt to delete it first, and
+ will fail if this can't be done.
+
+ Note that the destination file isn't the directory to put it in, it's the actual
+ filename that you want the new file to have.
+
+ @returns true if the operation succeeds
+ */
+ bool moveFileTo (const File& targetLocation) const;
+
+ /** Copies a file.
+
+ Tries to copy a file to a different location.
+ If the target file already exists, this will attempt to delete it first, and
+ will fail if this can't be done.
+
+ @returns true if the operation succeeds
+ */
+ bool copyFileTo (const File& targetLocation) const;
+
+ /** Copies a directory.
+
+ Tries to copy an entire directory, recursively.
+
+ If this file isn't a directory or if any target files can't be created, this
+ will return false.
+
+ @param newDirectory the directory that this one should be copied to. Note that this
+ is the name of the actual directory to create, not the directory
+ into which the new one should be placed, so there must be enough
+ write privileges to create it if it doesn't exist. Any files inside
+ it will be overwritten by similarly named ones that are copied.
+ */
+ bool copyDirectoryTo (const File& newDirectory) const;
+
+ //==============================================================================
+ /** Used in file searching, to specify whether to return files, directories, or both.
+ */
+ enum TypesOfFileToFind
+ {
+ findDirectories = 1, /**< Use this flag to indicate that you want to find directories. */
+ findFiles = 2, /**< Use this flag to indicate that you want to find files. */
+ findFilesAndDirectories = 3, /**< Use this flag to indicate that you want to find both files and directories. */
+ ignoreHiddenFiles = 4 /**< Add this flag to avoid returning any hidden files in the results. */
+ };
+
+ /** Searches inside a directory for files matching a wildcard pattern.
+
+ Assuming that this file is a directory, this method will search it
+ for either files or subdirectories whose names match a filename pattern.
+
+ @param results an array to which File objects will be added for the
+ files that the search comes up with
+ @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
+ return files, directories, or both. If the ignoreHiddenFiles flag
+ is also added to this value, hidden files won't be returned
+ @param searchRecursively if true, all subdirectories will be recursed into to do
+ an exhaustive search
+ @param wildCardPattern the filename pattern to search for, e.g. "*.txt"
+ @returns the number of results that have been found
+
+ @see getNumberOfChildFiles, DirectoryIterator
+ */
+ int findChildFiles (Array<File>& results,
+ int whatToLookFor,
+ bool searchRecursively,
+ const String& wildCardPattern = "*") const;
+
+ /** Searches inside a directory and counts how many files match a wildcard pattern.
+
+ Assuming that this file is a directory, this method will search it
+ for either files or subdirectories whose names match a filename pattern,
+ and will return the number of matches found.
+
+ This isn't a recursive call, and will only search this directory, not
+ its children.
+
+ @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
+ count files, directories, or both. If the ignoreHiddenFiles flag
+ is also added to this value, hidden files won't be counted
+ @param wildCardPattern the filename pattern to search for, e.g. "*.txt"
+ @returns the number of matches found
+ @see findChildFiles, DirectoryIterator
+ */
+ int getNumberOfChildFiles (int whatToLookFor,
+ const String& wildCardPattern = "*") const;
+
+ /** Returns true if this file is a directory that contains one or more subdirectories.
+ @see isDirectory, findChildFiles
+ */
+ bool containsSubDirectories() const;
+
+ //==============================================================================
+ /** Creates a stream to read from this file.
+
+ @returns a stream that will read from this file (initially positioned at the
+ start of the file), or nullptr if the file can't be opened for some reason
+ @see createOutputStream, loadFileAsData
+ */
+ FileInputStream* createInputStream() const;
+
+ /** Creates a stream to write to this file.
+
+ If the file exists, the stream that is returned will be positioned ready for
+ writing at the end of the file, so you might want to use deleteFile() first
+ to write to an empty file.
+
+ @returns a stream that will write to this file (initially positioned at the
+ end of the file), or nullptr if the file can't be opened for some reason
+ @see createInputStream, appendData, appendText
+ */
+ FileOutputStream* createOutputStream (size_t bufferSize = 0x8000) const;
+
+ //==============================================================================
+ /** Loads a file's contents into memory as a block of binary data.
+
+ Of course, trying to load a very large file into memory will blow up, so
+ it's better to check first.
+
+ @param result the data block to which the file's contents should be appended - note
+ that if the memory block might already contain some data, you
+ might want to clear it first
+ @returns true if the file could all be read into memory
+ */
+ bool loadFileAsData (MemoryBlock& result) const;
+
+ /** Reads a file into memory as a string.
+
+ Attempts to load the entire file as a zero-terminated string.
+
+ This makes use of InputStream::readEntireStreamAsString, which can
+ read either UTF-16 or UTF-8 file formats.
+ */
+ String loadFileAsString() const;
+
+ /** Reads the contents of this file as text and splits it into lines, which are
+ appended to the given StringArray.
+ */
+ void readLines (StringArray& destLines) const;
+
+ //==============================================================================
+ /** Appends a block of binary data to the end of the file.
+
+ This will try to write the given buffer to the end of the file.
+
+ @returns false if it can't write to the file for some reason
+ */
+ bool appendData (const void* dataToAppend,
+ size_t numberOfBytes) const;
+
+ /** Replaces this file's contents with a given block of data.
+
+ This will delete the file and replace it with the given data.
+
+ A nice feature of this method is that it's safe - instead of deleting
+ the file first and then re-writing it, it creates a new temporary file,
+ writes the data to that, and then moves the new file to replace the existing
+ file. This means that if the power gets pulled out or something crashes,
+ you're a lot less likely to end up with a corrupted or unfinished file..
+
+ Returns true if the operation succeeds, or false if it fails.
+
+ @see appendText
+ */
+ bool replaceWithData (const void* dataToWrite,
+ size_t numberOfBytes) const;
+
+ /** Appends a string to the end of the file.
+
+ This will try to append a text string to the file, as either 16-bit unicode
+ or 8-bit characters in the default system encoding.
+
+ It can also write the 'ff fe' unicode header bytes before the text to indicate
+ the endianness of the file.
+
+ Any single \\n characters in the string are replaced with \\r\\n before it is written.
+
+ @see replaceWithText
+ */
+ bool appendText (const String& textToAppend,
+ bool asUnicode = false,
+ bool writeUnicodeHeaderBytes = false) const;
+
+ /** Replaces this file's contents with a given text string.
+
+ This will delete the file and replace it with the given text.
+
+ A nice feature of this method is that it's safe - instead of deleting
+ the file first and then re-writing it, it creates a new temporary file,
+ writes the text to that, and then moves the new file to replace the existing
+ file. This means that if the power gets pulled out or something crashes,
+ you're a lot less likely to end up with an empty file..
+
+ For an explanation of the parameters here, see the appendText() method.
+
+ Returns true if the operation succeeds, or false if it fails.
+
+ @see appendText
+ */
+ bool replaceWithText (const String& textToWrite,
+ bool asUnicode = false,
+ bool writeUnicodeHeaderBytes = false) const;
+
+ /** Attempts to scan the contents of this file and compare it to another file, returning
+ true if this is possible and they match byte-for-byte.
+ */
+ bool hasIdenticalContentTo (const File& other) const;
+
+ //==============================================================================
+ /** Creates a set of files to represent each file root.
+
+ e.g. on Windows this will create files for "c:\", "d:\" etc according
+ to which ones are available. On the Mac/Linux, this will probably
+ just add a single entry for "/".
+ */
+ static void findFileSystemRoots (Array<File>& results);
+
+ /** Finds the name of the drive on which this file lives.
+ @returns the volume label of the drive, or an empty string if this isn't possible
+ */
+ String getVolumeLabel() const;
+
+ /** Returns the serial number of the volume on which this file lives.
+ @returns the serial number, or zero if there's a problem doing this
+ */
+ int getVolumeSerialNumber() const;
+
+ /** Returns the number of bytes free on the drive that this file lives on.
+
+ @returns the number of bytes free, or 0 if there's a problem finding this out
+ @see getVolumeTotalSize
+ */
+ int64 getBytesFreeOnVolume() const;
+
+ /** Returns the total size of the drive that contains this file.
+
+ @returns the total number of bytes that the volume can hold
+ @see getBytesFreeOnVolume
+ */
+ int64 getVolumeTotalSize() const;
+
+ /** Returns true if this file is on a CD or DVD drive. */
+ bool isOnCDRomDrive() const;
+
+ /** Returns true if this file is on a hard disk.
+
+ This will fail if it's a network drive, but will still be true for
+ removable hard-disks.
+ */
+ bool isOnHardDisk() const;
+
+ /** Returns true if this file is on a removable disk drive.
+
+ This might be a usb-drive, a CD-rom, or maybe a network drive.
+ */
+ bool isOnRemovableDrive() const;
+
+ //==============================================================================
+ /** Launches the file as a process.
+
+ - if the file is executable, this will run it.
+
+ - if it's a document of some kind, it will launch the document with its
+ default viewer application.
+
+ - if it's a folder, it will be opened in Explorer, Finder, or equivalent.
+
+ @see revealToUser
+ */
+ bool startAsProcess (const String& parameters = String()) const;
+
+ /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
+ @see startAsProcess
+ */
+ void revealToUser() const;
+
+ //==============================================================================
+ /** A set of types of location that can be passed to the getSpecialLocation() method.
+ */
+ enum SpecialLocationType
+ {
+ /** The user's home folder. This is the same as using File ("~"). */
+ userHomeDirectory,
+
+ /** The user's default documents folder. On Windows, this might be the user's
+ "My Documents" folder. On the Mac it'll be their "Documents" folder. Linux
+ doesn't tend to have one of these, so it might just return their home folder.
+ */
+ userDocumentsDirectory,
+
+ /** The folder that contains the user's desktop objects. */
+ userDesktopDirectory,
+
+ /** The most likely place where a user might store their music files. */
+ userMusicDirectory,
+
+ /** The most likely place where a user might store their movie files. */
+ userMoviesDirectory,
+
+ /** The most likely place where a user might store their picture files. */
+ userPicturesDirectory,
+
+ /** The folder in which applications store their persistent user-specific settings.
+ On Windows, this might be "\Documents and Settings\username\Application Data".
+ On the Mac, it might be "~/Library". If you're going to store your settings in here,
+ always create your own sub-folder to put them in, to avoid making a mess.
+ */
+ userApplicationDataDirectory,
+
+ /** An equivalent of the userApplicationDataDirectory folder that is shared by all users
+ of the computer, rather than just the current user.
+
+ On the Mac it'll be "/Library", on Windows, it could be something like
+ "\Documents and Settings\All Users\Application Data".
+
+ Depending on the setup, this folder may be read-only.
+ */
+ commonApplicationDataDirectory,
+
+ /** A place to put documents which are shared by all users of the machine.
+ On Windows this may be somewhere like "C:\Users\Public\Documents", on OSX it
+ will be something like "/Users/Shared". Other OSes may have no such concept
+ though, so be careful.
+ */
+ commonDocumentsDirectory,
+
+ /** The folder that should be used for temporary files.
+ Always delete them when you're finished, to keep the user's computer tidy!
+ */
+ tempDirectory,
+
+ /** Returns this application's executable file.
+
+ If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
+ host app.
+
+ On the mac this will return the unix binary, not the package folder - see
+ currentApplicationFile for that.
+
+ See also invokedExecutableFile, which is similar, but if the exe was launched from a
+ file link, invokedExecutableFile will return the name of the link.
+ */
+ currentExecutableFile,
+
+ /** Returns this application's location.
+
+ If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
+ host app.
+
+ On the mac this will return the package folder (if it's in one), not the unix binary
+ that's inside it - compare with currentExecutableFile.
+ */
+ currentApplicationFile,
+
+ /** Returns the file that was invoked to launch this executable.
+ This may differ from currentExecutableFile if the app was started from e.g. a link - this
+ will return the name of the link that was used, whereas currentExecutableFile will return
+ the actual location of the target executable.
+ */
+ invokedExecutableFile,
+
+ /** In a plugin, this will return the path of the host executable. */
+ hostApplicationPath,
+
+ #if JUCE_WINDOWS
+ /** On a Windows machine, returns the location of the Windows/System32 folder. */
+ windowsSystemDirectory,
+ #endif
+
+ /** The directory in which applications normally get installed.
+ So on windows, this would be something like "c:\program files", on the
+ Mac "/Applications", or "/usr" on linux.
+ */
+ globalApplicationsDirectory
+ };
+
+ /** Finds the location of a special type of file or directory, such as a home folder or
+ documents folder.
+
+ @see SpecialLocationType
+ */
+ static File JUCE_CALLTYPE getSpecialLocation (const SpecialLocationType type);
+
+ //==============================================================================
+ /** Returns a temporary file in the system's temp directory.
+ This will try to return the name of a non-existent temp file.
+ To get the temp folder, you can use getSpecialLocation (File::tempDirectory).
+ */
+ static File createTempFile (StringRef fileNameEnding);
+
+
+ //==============================================================================
+ /** Returns the current working directory.
+ @see setAsCurrentWorkingDirectory
+ */
+ static File getCurrentWorkingDirectory();
+
+ /** Sets the current working directory to be this file.
+
+ For this to work the file must point to a valid directory.
+
+ @returns true if the current directory has been changed.
+ @see getCurrentWorkingDirectory
+ */
+ bool setAsCurrentWorkingDirectory() const;
+
+ //==============================================================================
+ /** The system-specific file separator character.
+ On Windows, this will be '\', on Mac/Linux, it'll be '/'
+ */
+ static const juce_wchar separator;
+
+ /** The system-specific file separator character, as a string.
+ On Windows, this will be '\', on Mac/Linux, it'll be '/'
+ */
+ static const String separatorString;
+
+ //==============================================================================
+ /** Returns a version of a filename with any illegal characters removed.
+
+ This will return a copy of the given string after removing characters
+ that are not allowed in a legal filename, and possibly shortening the
+ string if it's too long.
+
+ Because this will remove slashes, don't use it on an absolute pathname - use
+ createLegalPathName() for that.
+
+ @see createLegalPathName
+ */
+ static String createLegalFileName (const String& fileNameToFix);
+
+ /** Returns a version of a path with any illegal characters removed.
+
+ Similar to createLegalFileName(), but this won't remove slashes, so can
+ be used on a complete pathname.
+
+ @see createLegalFileName
+ */
+ static String createLegalPathName (const String& pathNameToFix);
+
+ /** Indicates whether filenames are case-sensitive on the current operating system. */
+ static bool areFileNamesCaseSensitive();
+
+ /** Returns true if the string seems to be a fully-specified absolute path. */
+ static bool isAbsolutePath (StringRef path);
+
+ /** Creates a file that simply contains this string, without doing the sanity-checking
+ that the normal constructors do.
+
+ Best to avoid this unless you really know what you're doing.
+ */
+ static File createFileWithoutCheckingPath (const String& absolutePath) noexcept;
+
+ /** Adds a separator character to the end of a path if it doesn't already have one. */
+ static String addTrailingSeparator (const String& path);
+
+ #if JUCE_MAC || JUCE_IOS || DOXYGEN
+ //==============================================================================
+ /** OSX ONLY - Finds the OSType of a file from the its resources. */
+ OSType getMacOSType() const;
+
+ /** OSX ONLY - Returns true if this file is actually a bundle. */
+ bool isBundle() const;
+ #endif
+
+ #if JUCE_MAC || DOXYGEN
+ /** OSX ONLY - Adds this file to the OSX dock */
+ void addToDock() const;
+ #endif
+
+ #if JUCE_WINDOWS
+ /** Windows ONLY - Creates a win32 .LNK shortcut file that links to this file. */
+ bool createLink (const String& description, const File& linkFileToCreate) const;
+ #endif
+
+private:
+ //==============================================================================
+ String fullPath;
+
+ static String parseAbsolutePath (const String&);
+ String getPathUpToLastSlash() const;
+
+ Result createDirectoryInternal (const String&) const;
+ bool copyInternal (const File&) const;
+ bool moveInternal (const File&) const;
+ bool setFileTimesInternal (int64 m, int64 a, int64 c) const;
+ void getFileTimesInternal (int64& m, int64& a, int64& c) const;
+ bool setFileReadOnlyInternal (bool) const;
+};
+
+#endif // JUCE_FILE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.cpp
new file mode 100644
index 0000000..bd0bdf8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.cpp
@@ -0,0 +1,41 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+FileFilter::FileFilter (const String& filterDescription)
+ : description (filterDescription)
+{
+}
+
+FileFilter::~FileFilter()
+{
+}
+
+const String& FileFilter::getDescription() const noexcept
+{
+ return description;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.h
new file mode 100644
index 0000000..4c02415
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileFilter.h
@@ -0,0 +1,77 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILEFILTER_H_INCLUDED
+#define JUCE_FILEFILTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Interface for deciding which files are suitable for something.
+
+ For example, this is used by DirectoryContentsList to select which files
+ go into the list.
+
+ @see WildcardFileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent
+*/
+class JUCE_API FileFilter
+{
+public:
+ //==============================================================================
+ /** Creates a filter with the given description.
+
+ The description can be returned later with the getDescription() method.
+ */
+ FileFilter (const String& filterDescription);
+
+ /** Destructor. */
+ virtual ~FileFilter();
+
+ //==============================================================================
+ /** Returns the description that the filter was created with. */
+ const String& getDescription() const noexcept;
+
+ //==============================================================================
+ /** Should return true if this file is suitable for inclusion in whatever context
+ the object is being used.
+ */
+ virtual bool isFileSuitable (const File& file) const = 0;
+
+ /** Should return true if this directory is suitable for inclusion in whatever context
+ the object is being used.
+ */
+ virtual bool isDirectorySuitable (const File& file) const = 0;
+
+
+protected:
+ //==============================================================================
+ String description;
+};
+
+
+#endif // JUCE_FILEFILTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.cpp
new file mode 100644
index 0000000..801ccfa
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.cpp
@@ -0,0 +1,84 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+int64 juce_fileSetPosition (void* handle, int64 pos);
+
+
+//==============================================================================
+FileInputStream::FileInputStream (const File& f)
+ : file (f),
+ fileHandle (nullptr),
+ currentPosition (0),
+ status (Result::ok())
+{
+ openHandle();
+}
+
+int64 FileInputStream::getTotalLength()
+{
+ // You should always check that a stream opened successfully before using it!
+ jassert (openedOk());
+
+ return file.getSize();
+}
+
+int FileInputStream::read (void* buffer, int bytesToRead)
+{
+ // You should always check that a stream opened successfully before using it!
+ jassert (openedOk());
+
+ // The buffer should never be null, and a negative size is probably a
+ // sign that something is broken!
+ jassert (buffer != nullptr && bytesToRead >= 0);
+
+ const size_t num = readInternal (buffer, (size_t) bytesToRead);
+ currentPosition += num;
+
+ return (int) num;
+}
+
+bool FileInputStream::isExhausted()
+{
+ return currentPosition >= getTotalLength();
+}
+
+int64 FileInputStream::getPosition()
+{
+ return currentPosition;
+}
+
+bool FileInputStream::setPosition (int64 pos)
+{
+ // You should always check that a stream opened successfully before using it!
+ jassert (openedOk());
+
+ if (pos != currentPosition)
+ currentPosition = juce_fileSetPosition (fileHandle, pos);
+
+ return currentPosition == pos;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.h
new file mode 100644
index 0000000..35963ba
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileInputStream.h
@@ -0,0 +1,96 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILEINPUTSTREAM_H_INCLUDED
+#define JUCE_FILEINPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ An input stream that reads from a local file.
+
+ @see InputStream, FileOutputStream, File::createInputStream
+*/
+class JUCE_API FileInputStream : public InputStream
+{
+public:
+ //==============================================================================
+ /** Creates a FileInputStream to read from the given file.
+
+ After creating a FileInputStream, you should use openedOk() or failedToOpen()
+ to make sure that it's OK before trying to read from it! If it failed, you
+ can call getStatus() to get more error information.
+ */
+ explicit FileInputStream (const File& fileToRead);
+
+ /** Destructor. */
+ ~FileInputStream();
+
+ //==============================================================================
+ /** Returns the file that this stream is reading from. */
+ const File& getFile() const noexcept { return file; }
+
+ /** Returns the status of the file stream.
+ The result will be ok if the file opened successfully. If an error occurs while
+ opening or reading from the file, this will contain an error message.
+ */
+ const Result& getStatus() const noexcept { return status; }
+
+ /** Returns true if the stream couldn't be opened for some reason.
+ @see getResult()
+ */
+ bool failedToOpen() const noexcept { return status.failed(); }
+
+ /** Returns true if the stream opened without problems.
+ @see getResult()
+ */
+ bool openedOk() const noexcept { return status.wasOk(); }
+
+
+ //==============================================================================
+ int64 getTotalLength() override;
+ int read (void*, int) override;
+ bool isExhausted() override;
+ int64 getPosition() override;
+ bool setPosition (int64) override;
+
+private:
+ //==============================================================================
+ const File file;
+ void* fileHandle;
+ int64 currentPosition;
+ Result status;
+
+ void openHandle();
+ size_t readInternal (void*, size_t);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileInputStream)
+};
+
+
+#endif // JUCE_FILEINPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.cpp
new file mode 100644
index 0000000..961a8d1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.cpp
@@ -0,0 +1,134 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+int64 juce_fileSetPosition (void* handle, int64 pos);
+
+//==============================================================================
+FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse)
+ : file (f),
+ fileHandle (nullptr),
+ status (Result::ok()),
+ currentPosition (0),
+ bufferSize (bufferSizeToUse),
+ bytesInBuffer (0),
+ buffer (jmax (bufferSizeToUse, (size_t) 16))
+{
+ openHandle();
+}
+
+FileOutputStream::~FileOutputStream()
+{
+ flushBuffer();
+ closeHandle();
+}
+
+int64 FileOutputStream::getPosition()
+{
+ return currentPosition;
+}
+
+bool FileOutputStream::setPosition (int64 newPosition)
+{
+ if (newPosition != currentPosition)
+ {
+ flushBuffer();
+ currentPosition = juce_fileSetPosition (fileHandle, newPosition);
+ }
+
+ return newPosition == currentPosition;
+}
+
+bool FileOutputStream::flushBuffer()
+{
+ bool ok = true;
+
+ if (bytesInBuffer > 0)
+ {
+ ok = (writeInternal (buffer, bytesInBuffer) == (ssize_t) bytesInBuffer);
+ bytesInBuffer = 0;
+ }
+
+ return ok;
+}
+
+void FileOutputStream::flush()
+{
+ flushBuffer();
+ flushInternal();
+}
+
+bool FileOutputStream::write (const void* const src, const size_t numBytes)
+{
+ jassert (src != nullptr && ((ssize_t) numBytes) >= 0);
+
+ if (bytesInBuffer + numBytes < bufferSize)
+ {
+ memcpy (buffer + bytesInBuffer, src, numBytes);
+ bytesInBuffer += numBytes;
+ currentPosition += numBytes;
+ }
+ else
+ {
+ if (! flushBuffer())
+ return false;
+
+ if (numBytes < bufferSize)
+ {
+ memcpy (buffer + bytesInBuffer, src, numBytes);
+ bytesInBuffer += numBytes;
+ currentPosition += numBytes;
+ }
+ else
+ {
+ const ssize_t bytesWritten = writeInternal (src, numBytes);
+
+ if (bytesWritten < 0)
+ return false;
+
+ currentPosition += bytesWritten;
+ return bytesWritten == (ssize_t) numBytes;
+ }
+ }
+
+ return true;
+}
+
+bool FileOutputStream::writeRepeatedByte (uint8 byte, size_t numBytes)
+{
+ jassert (((ssize_t) numBytes) >= 0);
+
+ if (bytesInBuffer + numBytes < bufferSize)
+ {
+ memset (buffer + bytesInBuffer, byte, numBytes);
+ bytesInBuffer += numBytes;
+ currentPosition += numBytes;
+ return true;
+ }
+
+ return OutputStream::writeRepeatedByte (byte, numBytes);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.h
new file mode 100644
index 0000000..f80705f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileOutputStream.h
@@ -0,0 +1,116 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILEOUTPUTSTREAM_H_INCLUDED
+#define JUCE_FILEOUTPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ An output stream that writes into a local file.
+
+ @see OutputStream, FileInputStream, File::createOutputStream
+*/
+class JUCE_API FileOutputStream : public OutputStream
+{
+public:
+ //==============================================================================
+ /** Creates a FileOutputStream.
+
+ If the file doesn't exist, it will first be created. If the file can't be
+ created or opened, the failedToOpen() method will return
+ true.
+
+ If the file already exists when opened, the stream's write-postion will
+ be set to the end of the file. To overwrite an existing file,
+ use File::deleteFile() before opening the stream, or use setPosition(0)
+ after it's opened (although this won't truncate the file).
+
+ @see TemporaryFile
+ */
+ FileOutputStream (const File& fileToWriteTo,
+ size_t bufferSizeToUse = 16384);
+
+ /** Destructor. */
+ ~FileOutputStream();
+
+ //==============================================================================
+ /** Returns the file that this stream is writing to.
+ */
+ const File& getFile() const { return file; }
+
+ /** Returns the status of the file stream.
+ The result will be ok if the file opened successfully. If an error occurs while
+ opening or writing to the file, this will contain an error message.
+ */
+ const Result& getStatus() const noexcept { return status; }
+
+ /** Returns true if the stream couldn't be opened for some reason.
+ @see getResult()
+ */
+ bool failedToOpen() const noexcept { return status.failed(); }
+
+ /** Returns true if the stream opened without problems.
+ @see getResult()
+ */
+ bool openedOk() const noexcept { return status.wasOk(); }
+
+ /** Attempts to truncate the file to the current write position.
+ To truncate a file to a specific size, first use setPosition() to seek to the
+ appropriate location, and then call this method.
+ */
+ Result truncate();
+
+ //==============================================================================
+ void flush() override;
+ int64 getPosition() override;
+ bool setPosition (int64) override;
+ bool write (const void*, size_t) override;
+ bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override;
+
+
+private:
+ //==============================================================================
+ File file;
+ void* fileHandle;
+ Result status;
+ int64 currentPosition;
+ size_t bufferSize, bytesInBuffer;
+ HeapBlock <char> buffer;
+
+ void openHandle();
+ void closeHandle();
+ void flushInternal();
+ bool flushBuffer();
+ int64 setPositionInternal (int64);
+ ssize_t writeInternal (const void*, size_t);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileOutputStream)
+};
+
+#endif // JUCE_FILEOUTPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.cpp
new file mode 100644
index 0000000..ce0af7e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.cpp
@@ -0,0 +1,172 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+FileSearchPath::FileSearchPath() {}
+FileSearchPath::~FileSearchPath() {}
+
+FileSearchPath::FileSearchPath (const String& path)
+{
+ init (path);
+}
+
+FileSearchPath::FileSearchPath (const FileSearchPath& other)
+ : directories (other.directories)
+{
+}
+
+FileSearchPath& FileSearchPath::operator= (const FileSearchPath& other)
+{
+ directories = other.directories;
+ return *this;
+}
+
+FileSearchPath& FileSearchPath::operator= (const String& path)
+{
+ init (path);
+ return *this;
+}
+
+void FileSearchPath::init (const String& path)
+{
+ directories.clear();
+ directories.addTokens (path, ";", "\"");
+ directories.trim();
+ directories.removeEmptyStrings();
+
+ for (int i = directories.size(); --i >= 0;)
+ directories.set (i, directories[i].unquoted());
+}
+
+int FileSearchPath::getNumPaths() const
+{
+ return directories.size();
+}
+
+File FileSearchPath::operator[] (const int index) const
+{
+ return File (directories [index]);
+}
+
+String FileSearchPath::toString() const
+{
+ StringArray directories2 (directories);
+ for (int i = directories2.size(); --i >= 0;)
+ if (directories2[i].containsChar (';'))
+ directories2.set (i, directories2[i].quoted());
+
+ return directories2.joinIntoString (";");
+}
+
+void FileSearchPath::add (const File& dir, const int insertIndex)
+{
+ directories.insert (insertIndex, dir.getFullPathName());
+}
+
+void FileSearchPath::addIfNotAlreadyThere (const File& dir)
+{
+ for (int i = 0; i < directories.size(); ++i)
+ if (File (directories[i]) == dir)
+ return;
+
+ add (dir);
+}
+
+void FileSearchPath::remove (const int index)
+{
+ directories.remove (index);
+}
+
+void FileSearchPath::addPath (const FileSearchPath& other)
+{
+ for (int i = 0; i < other.getNumPaths(); ++i)
+ addIfNotAlreadyThere (other[i]);
+}
+
+void FileSearchPath::removeRedundantPaths()
+{
+ for (int i = directories.size(); --i >= 0;)
+ {
+ const File d1 (directories[i]);
+
+ for (int j = directories.size(); --j >= 0;)
+ {
+ const File d2 (directories[j]);
+
+ if ((i != j) && (d1.isAChildOf (d2) || d1 == d2))
+ {
+ directories.remove (i);
+ break;
+ }
+ }
+ }
+}
+
+void FileSearchPath::removeNonExistentPaths()
+{
+ for (int i = directories.size(); --i >= 0;)
+ if (! File (directories[i]).isDirectory())
+ directories.remove (i);
+}
+
+int FileSearchPath::findChildFiles (Array<File>& results,
+ const int whatToLookFor,
+ const bool searchRecursively,
+ const String& wildCardPattern) const
+{
+ int total = 0;
+
+ for (int i = 0; i < directories.size(); ++i)
+ total += operator[] (i).findChildFiles (results,
+ whatToLookFor,
+ searchRecursively,
+ wildCardPattern);
+
+ return total;
+}
+
+bool FileSearchPath::isFileInPath (const File& fileToCheck,
+ const bool checkRecursively) const
+{
+ for (int i = directories.size(); --i >= 0;)
+ {
+ const File d (directories[i]);
+
+ if (checkRecursively)
+ {
+ if (fileToCheck.isAChildOf (d))
+ return true;
+ }
+ else
+ {
+ if (fileToCheck.getParentDirectory() == d)
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.h
new file mode 100644
index 0000000..51baf2e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_FileSearchPath.h
@@ -0,0 +1,165 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILESEARCHPATH_H_INCLUDED
+#define JUCE_FILESEARCHPATH_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a set of folders that make up a search path.
+
+ @see File
+*/
+class JUCE_API FileSearchPath
+{
+public:
+ //==============================================================================
+ /** Creates an empty search path. */
+ FileSearchPath();
+
+ /** Creates a search path from a string of pathnames.
+
+ The path can be semicolon- or comma-separated, e.g.
+ "/foo/bar;/foo/moose;/fish/moose"
+
+ The separate folders are tokenised and added to the search path.
+ */
+ FileSearchPath (const String& path);
+
+ /** Creates a copy of another search path. */
+ FileSearchPath (const FileSearchPath&);
+
+ /** Copies another search path. */
+ FileSearchPath& operator= (const FileSearchPath&);
+
+ /** Destructor. */
+ ~FileSearchPath();
+
+ /** Uses a string containing a list of pathnames to re-initialise this list.
+
+ This search path is cleared and the semicolon- or comma-separated folders
+ in this string are added instead. e.g. "/foo/bar;/foo/moose;/fish/moose"
+ */
+ FileSearchPath& operator= (const String& path);
+
+ //==============================================================================
+ /** Returns the number of folders in this search path.
+ @see operator[]
+ */
+ int getNumPaths() const;
+
+ /** Returns one of the folders in this search path.
+ The file returned isn't guaranteed to actually be a valid directory.
+ @see getNumPaths
+ */
+ File operator[] (int index) const;
+
+ /** Returns the search path as a semicolon-separated list of directories. */
+ String toString() const;
+
+ //==============================================================================
+ /** Adds a new directory to the search path.
+
+ The new directory is added to the end of the list if the insertIndex parameter is
+ less than zero, otherwise it is inserted at the given index.
+ */
+ void add (const File& directoryToAdd,
+ int insertIndex = -1);
+
+ /** Adds a new directory to the search path if it's not already in there. */
+ void addIfNotAlreadyThere (const File& directoryToAdd);
+
+ /** Removes a directory from the search path. */
+ void remove (int indexToRemove);
+
+ /** Merges another search path into this one.
+ This will remove any duplicate directories.
+ */
+ void addPath (const FileSearchPath&);
+
+ /** Removes any directories that are actually subdirectories of one of the other directories in the search path.
+
+ If the search is intended to be recursive, there's no point having nested folders in the search
+ path, because they'll just get searched twice and you'll get duplicate results.
+
+ e.g. if the path is "c:\abc\de;c:\abc", this method will simplify it to "c:\abc"
+ */
+ void removeRedundantPaths();
+
+ /** Removes any directories that don't actually exist. */
+ void removeNonExistentPaths();
+
+ //==============================================================================
+ /** Searches the path for a wildcard.
+
+ This will search all the directories in the search path in order, adding any
+ matching files to the results array.
+
+ @param results an array to append the results to
+ @param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying whether to
+ return files, directories, or both.
+ @param searchRecursively whether to recursively search the subdirectories too
+ @param wildCardPattern a pattern to match against the filenames
+ @returns the number of files added to the array
+ @see File::findChildFiles
+ */
+ int findChildFiles (Array<File>& results,
+ int whatToLookFor,
+ bool searchRecursively,
+ const String& wildCardPattern = "*") const;
+
+ //==============================================================================
+ /** Finds out whether a file is inside one of the path's directories.
+
+ This will return true if the specified file is a child of one of the
+ directories specified by this path. Note that this doesn't actually do any
+ searching or check that the files exist - it just looks at the pathnames
+ to work out whether the file would be inside a directory.
+
+ @param fileToCheck the file to look for
+ @param checkRecursively if true, then this will return true if the file is inside a
+ subfolder of one of the path's directories (at any depth). If false
+ it will only return true if the file is actually a direct child
+ of one of the directories.
+ @see File::isAChildOf
+
+ */
+ bool isFileInPath (const File& fileToCheck,
+ bool checkRecursively) const;
+
+private:
+ //==============================================================================
+ StringArray directories;
+
+ void init (const String&);
+
+ JUCE_LEAK_DETECTOR (FileSearchPath)
+};
+
+#endif // JUCE_FILESEARCHPATH_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_MemoryMappedFile.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_MemoryMappedFile.h
new file mode 100644
index 0000000..8a79185
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_MemoryMappedFile.h
@@ -0,0 +1,115 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MEMORYMAPPEDFILE_H_INCLUDED
+#define JUCE_MEMORYMAPPEDFILE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Maps a file into virtual memory for easy reading and/or writing.
+*/
+class JUCE_API MemoryMappedFile
+{
+public:
+ /** The read/write flags used when opening a memory mapped file. */
+ enum AccessMode
+ {
+ readOnly, /**< Indicates that the memory can only be read. */
+ readWrite /**< Indicates that the memory can be read and written to - changes that are
+ made will be flushed back to disk at the whim of the OS. */
+ };
+
+ /** Opens a file and maps it to an area of virtual memory.
+
+ The file should already exist, and should already be the size that you want to work with
+ when you call this. If the file is resized after being opened, the behaviour is undefined.
+
+ If the file exists and the operation succeeds, the getData() and getSize() methods will
+ return the location and size of the data that can be read or written. Note that the entire
+ file is not read into memory immediately - the OS simply creates a virtual mapping, which
+ will lazily pull the data into memory when blocks are accessed.
+
+ If the file can't be opened for some reason, the getData() method will return a null pointer.
+ */
+ MemoryMappedFile (const File& file, AccessMode mode);
+
+ /** Opens a section of a file and maps it to an area of virtual memory.
+
+ The file should already exist, and should already be the size that you want to work with
+ when you call this. If the file is resized after being opened, the behaviour is undefined.
+
+ If the file exists and the operation succeeds, the getData() and getSize() methods will
+ return the location and size of the data that can be read or written. Note that the entire
+ file is not read into memory immediately - the OS simply creates a virtual mapping, which
+ will lazily pull the data into memory when blocks are accessed.
+
+ If the file can't be opened for some reason, the getData() method will return a null pointer.
+
+ NOTE: the start of the actual range used may be rounded-down to a multiple of the OS's page-size,
+ so do not assume that the mapped memory will begin at exactly the position you requested - always
+ use getRange() to check the actual range that is being used.
+ */
+ MemoryMappedFile (const File& file,
+ const Range<int64>& fileRange,
+ AccessMode mode);
+
+ /** Destructor. */
+ ~MemoryMappedFile();
+
+ /** Returns the address at which this file has been mapped, or a null pointer if
+ the file couldn't be successfully mapped.
+ */
+ void* getData() const noexcept { return address; }
+
+ /** Returns the number of bytes of data that are available for reading or writing.
+ This will normally be the size of the file.
+ */
+ size_t getSize() const noexcept { return (size_t) range.getLength(); }
+
+ /** Returns the section of the file at which the mapped memory represents. */
+ Range<int64> getRange() const noexcept { return range; }
+
+private:
+ //==============================================================================
+ void* address;
+ Range<int64> range;
+
+ #if JUCE_WINDOWS
+ void* fileHandle;
+ #else
+ int fileHandle;
+ #endif
+
+ void openInternal (const File&, AccessMode);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedFile)
+};
+
+
+#endif // JUCE_MEMORYMAPPEDFILE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.cpp
new file mode 100644
index 0000000..50475d5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.cpp
@@ -0,0 +1,117 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+static File createTempFile (const File& parentDirectory, String name,
+ const String& suffix, const int optionFlags)
+{
+ if ((optionFlags & TemporaryFile::useHiddenFile) != 0)
+ name = "." + name;
+
+ return parentDirectory.getNonexistentChildFile (name, suffix, (optionFlags & TemporaryFile::putNumbersInBrackets) != 0);
+}
+
+TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags)
+ : temporaryFile (createTempFile (File::getSpecialLocation (File::tempDirectory),
+ "temp_" + String::toHexString (Random::getSystemRandom().nextInt()),
+ suffix, optionFlags))
+{
+}
+
+TemporaryFile::TemporaryFile (const File& target, const int optionFlags)
+ : temporaryFile (createTempFile (target.getParentDirectory(),
+ target.getFileNameWithoutExtension()
+ + "_temp" + String::toHexString (Random::getSystemRandom().nextInt()),
+ target.getFileExtension(), optionFlags)),
+ targetFile (target)
+{
+ // If you use this constructor, you need to give it a valid target file!
+ jassert (targetFile != File());
+}
+
+TemporaryFile::TemporaryFile (const File& target, const File& temporary)
+ : temporaryFile (temporary), targetFile (target)
+{
+}
+
+TemporaryFile::~TemporaryFile()
+{
+ if (! deleteTemporaryFile())
+ {
+ /* Failed to delete our temporary file! The most likely reason for this would be
+ that you've not closed an output stream that was being used to write to file.
+
+ If you find that something beyond your control is changing permissions on
+ your temporary files and preventing them from being deleted, you may want to
+ call TemporaryFile::deleteTemporaryFile() to detect those error cases and
+ handle them appropriately.
+ */
+ jassertfalse;
+ }
+}
+
+//==============================================================================
+bool TemporaryFile::overwriteTargetFileWithTemporary() const
+{
+ // This method only works if you created this object with the constructor
+ // that takes a target file!
+ jassert (targetFile != File());
+
+ if (temporaryFile.exists())
+ {
+ // Have a few attempts at overwriting the file before giving up..
+ for (int i = 5; --i >= 0;)
+ {
+ if (temporaryFile.moveFileTo (targetFile))
+ return true;
+
+ Thread::sleep (100);
+ }
+ }
+ else
+ {
+ // There's no temporary file to use. If your write failed, you should
+ // probably check, and not bother calling this method.
+ jassertfalse;
+ }
+
+ return false;
+}
+
+bool TemporaryFile::deleteTemporaryFile() const
+{
+ // Have a few attempts at deleting the file before giving up..
+ for (int i = 5; --i >= 0;)
+ {
+ if (temporaryFile.deleteFile())
+ return true;
+
+ Thread::sleep (50);
+ }
+
+ return false;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.h
new file mode 100644
index 0000000..04561a7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_TemporaryFile.h
@@ -0,0 +1,169 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_TEMPORARYFILE_H_INCLUDED
+#define JUCE_TEMPORARYFILE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Manages a temporary file, which will be deleted when this object is deleted.
+
+ This object is intended to be used as a stack based object, using its scope
+ to make sure the temporary file isn't left lying around.
+
+ For example:
+
+ @code
+ {
+ File myTargetFile ("~/myfile.txt");
+
+ // this will choose a file called something like "~/myfile_temp239348.txt"
+ // which definitely doesn't exist at the time the constructor is called.
+ TemporaryFile temp (myTargetFile);
+
+ // create a stream to the temporary file, and write some data to it...
+ ScopedPointer <FileOutputStream> out (temp.getFile().createOutputStream());
+
+ if (out != nullptr)
+ {
+ out->write ( ...etc )
+ out = nullptr; // (deletes the stream)
+
+ // ..now we've finished writing, this will rename the temp file to
+ // make it replace the target file we specified above.
+ bool succeeded = temp.overwriteTargetFileWithTemporary();
+ }
+
+ // ..and even if something went wrong and our overwrite failed,
+ // as the TemporaryFile object goes out of scope here, it'll make sure
+ // that the temp file gets deleted.
+ }
+ @endcode
+
+ @see File, FileOutputStream
+*/
+class JUCE_API TemporaryFile
+{
+public:
+ //==============================================================================
+ enum OptionFlags
+ {
+ useHiddenFile = 1, /**< Indicates that the temporary file should be hidden -
+ i.e. its name should start with a dot. */
+ putNumbersInBrackets = 2 /**< Indicates that when numbers are appended to make sure
+ the file is unique, they should go in brackets rather
+ than just being appended (see File::getNonexistentSibling() )*/
+ };
+
+ //==============================================================================
+ /** Creates a randomly-named temporary file in the default temp directory.
+
+ @param suffix a file suffix to use for the file
+ @param optionFlags a combination of the values listed in the OptionFlags enum
+ The file will not be created until you write to it. And remember that when
+ this object is deleted, the file will also be deleted!
+ */
+ TemporaryFile (const String& suffix = String(),
+ int optionFlags = 0);
+
+ /** Creates a temporary file in the same directory as a specified file.
+
+ This is useful if you have a file that you want to overwrite, but don't
+ want to harm the original file if the write operation fails. You can
+ use this to create a temporary file next to the target file, then
+ write to the temporary file, and finally use overwriteTargetFileWithTemporary()
+ to replace the target file with the one you've just written.
+
+ This class won't create any files until you actually write to them. And remember
+ that when this object is deleted, the temporary file will also be deleted!
+
+ @param targetFile the file that you intend to overwrite - the temporary
+ file will be created in the same directory as this
+ @param optionFlags a combination of the values listed in the OptionFlags enum
+ */
+ TemporaryFile (const File& targetFile,
+ int optionFlags = 0);
+
+ /** Creates a temporary file using an explicit filename.
+ The other constructors are a better choice than this one, unless for some reason
+ you need to explicitly specify the temporary file you want to use.
+
+ @param targetFile the file that you intend to overwrite
+ @param temporaryFile the temporary file to be used
+ */
+ TemporaryFile (const File& targetFile,
+ const File& temporaryFile);
+
+ /** Destructor.
+
+ When this object is deleted it will make sure that its temporary file is
+ also deleted! If the operation fails, it'll throw an assertion in debug
+ mode.
+ */
+ ~TemporaryFile();
+
+ //==============================================================================
+ /** Returns the temporary file. */
+ const File& getFile() const noexcept { return temporaryFile; }
+
+ /** Returns the target file that was specified in the constructor. */
+ const File& getTargetFile() const noexcept { return targetFile; }
+
+ /** Tries to move the temporary file to overwrite the target file that was
+ specified in the constructor.
+
+ If you used the constructor that specified a target file, this will attempt
+ to replace that file with the temporary one.
+
+ Before calling this, make sure:
+ - that you've actually written to the temporary file
+ - that you've closed any open streams that you were using to write to it
+ - and that you don't have any streams open to the target file, which would
+ prevent it being overwritten
+
+ If the file move succeeds, this returns false, and the temporary file will
+ have disappeared. If it fails, the temporary file will probably still exist,
+ but will be deleted when this object is destroyed.
+ */
+ bool overwriteTargetFileWithTemporary() const;
+
+ /** Attempts to delete the temporary file, if it exists.
+ @returns true if the file is successfully deleted (or if it didn't exist).
+ */
+ bool deleteTemporaryFile() const;
+
+
+private:
+ //==============================================================================
+ const File temporaryFile, targetFile;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemporaryFile)
+};
+
+#endif // JUCE_TEMPORARYFILE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.cpp
new file mode 100644
index 0000000..1fef455
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.cpp
@@ -0,0 +1,77 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns,
+ const String& directoryWildcardPatterns,
+ const String& desc)
+ : FileFilter (desc.isEmpty() ? fileWildcardPatterns
+ : (desc + " (" + fileWildcardPatterns + ")"))
+{
+ parse (fileWildcardPatterns, fileWildcards);
+ parse (directoryWildcardPatterns, directoryWildcards);
+}
+
+WildcardFileFilter::~WildcardFileFilter()
+{
+}
+
+bool WildcardFileFilter::isFileSuitable (const File& file) const
+{
+ return match (file, fileWildcards);
+}
+
+bool WildcardFileFilter::isDirectorySuitable (const File& file) const
+{
+ return match (file, directoryWildcards);
+}
+
+//==============================================================================
+void WildcardFileFilter::parse (const String& pattern, StringArray& result)
+{
+ result.addTokens (pattern.toLowerCase(), ";,", "\"'");
+
+ result.trim();
+ result.removeEmptyStrings();
+
+ // special case for *.*, because people use it to mean "any file", but it
+ // would actually ignore files with no extension.
+ for (int i = result.size(); --i >= 0;)
+ if (result[i] == "*.*")
+ result.set (i, "*");
+}
+
+bool WildcardFileFilter::match (const File& file, const StringArray& wildcards)
+{
+ const String filename (file.getFileName());
+
+ for (int i = wildcards.size(); --i >= 0;)
+ if (filename.matchesWildcard (wildcards[i], true))
+ return true;
+
+ return false;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.h b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.h
new file mode 100644
index 0000000..166ae4a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/files/juce_WildcardFileFilter.h
@@ -0,0 +1,86 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_WILDCARDFILEFILTER_H_INCLUDED
+#define JUCE_WILDCARDFILEFILTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A type of FileFilter that works by wildcard pattern matching.
+
+ This filter only allows files that match one of the specified patterns, but
+ allows all directories through.
+
+ @see FileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent
+*/
+class JUCE_API WildcardFileFilter : public FileFilter
+{
+public:
+ //==============================================================================
+ /**
+ Creates a wildcard filter for one or more patterns.
+
+ The wildcardPatterns parameter is a comma or semicolon-delimited set of
+ patterns, e.g. "*.wav;*.aiff" would look for files ending in either .wav
+ or .aiff.
+
+ Passing an empty string as a pattern will fail to match anything, so by leaving
+ either the file or directory pattern parameter empty means you can control
+ whether files or directories are found.
+
+ The description is a name to show the user in a list of possible patterns, so
+ for the wav/aiff example, your description might be "audio files".
+ */
+ WildcardFileFilter (const String& fileWildcardPatterns,
+ const String& directoryWildcardPatterns,
+ const String& description);
+
+ /** Destructor. */
+ ~WildcardFileFilter();
+
+ //==============================================================================
+ /** Returns true if the filename matches one of the patterns specified. */
+ bool isFileSuitable (const File& file) const;
+
+ /** This always returns true. */
+ bool isDirectorySuitable (const File& file) const;
+
+private:
+ //==============================================================================
+ StringArray fileWildcards, directoryWildcards;
+
+ static void parse (const String& pattern, StringArray& result);
+ static bool match (const File& file, const StringArray& wildcards);
+
+ JUCE_LEAK_DETECTOR (WildcardFileFilter)
+};
+
+
+
+#endif // JUCE_WILDCARDFILEFILTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.cpp
new file mode 100644
index 0000000..5a0f7f7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.cpp
@@ -0,0 +1,643 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class JSONParser
+{
+public:
+ static Result parseObjectOrArray (String::CharPointerType t, var& result)
+ {
+ t = t.findEndOfWhitespace();
+
+ switch (t.getAndAdvance())
+ {
+ case 0: result = var(); return Result::ok();
+ case '{': return parseObject (t, result);
+ case '[': return parseArray (t, result);
+ }
+
+ return createFail ("Expected '{' or '['", &t);
+ }
+
+ static Result parseString (const juce_wchar quoteChar, String::CharPointerType& t, var& result)
+ {
+ MemoryOutputStream buffer (256);
+
+ for (;;)
+ {
+ juce_wchar c = t.getAndAdvance();
+
+ if (c == quoteChar)
+ break;
+
+ if (c == '\\')
+ {
+ c = t.getAndAdvance();
+
+ switch (c)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ case '/': break;
+
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+
+ case 'u':
+ {
+ c = 0;
+
+ for (int i = 4; --i >= 0;)
+ {
+ const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
+ if (digitValue < 0)
+ return createFail ("Syntax error in unicode escape sequence");
+
+ c = (juce_wchar) ((c << 4) + digitValue);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (c == 0)
+ return createFail ("Unexpected end-of-input in string constant");
+
+ buffer.appendUTF8Char (c);
+ }
+
+ result = buffer.toUTF8();
+ return Result::ok();
+ }
+
+ static Result parseAny (String::CharPointerType& t, var& result)
+ {
+ t = t.findEndOfWhitespace();
+ String::CharPointerType t2 (t);
+
+ switch (t2.getAndAdvance())
+ {
+ case '{': t = t2; return parseObject (t, result);
+ case '[': t = t2; return parseArray (t, result);
+ case '"': t = t2; return parseString ('"', t, result);
+ case '\'': t = t2; return parseString ('\'', t, result);
+
+ case '-':
+ t2 = t2.findEndOfWhitespace();
+ if (! CharacterFunctions::isDigit (*t2))
+ break;
+
+ t = t2;
+ return parseNumber (t, result, true);
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return parseNumber (t, result, false);
+
+ case 't': // "true"
+ if (t2.getAndAdvance() == 'r' && t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'e')
+ {
+ t = t2;
+ result = var (true);
+ return Result::ok();
+ }
+ break;
+
+ case 'f': // "false"
+ if (t2.getAndAdvance() == 'a' && t2.getAndAdvance() == 'l'
+ && t2.getAndAdvance() == 's' && t2.getAndAdvance() == 'e')
+ {
+ t = t2;
+ result = var (false);
+ return Result::ok();
+ }
+ break;
+
+ case 'n': // "null"
+ if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
+ {
+ t = t2;
+ result = var();
+ return Result::ok();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return createFail ("Syntax error", &t);
+ }
+
+private:
+ static Result createFail (const char* const message, const String::CharPointerType* location = nullptr)
+ {
+ String m (message);
+ if (location != nullptr)
+ m << ": \"" << String (*location, 20) << '"';
+
+ return Result::fail (m);
+ }
+
+ static Result parseNumber (String::CharPointerType& t, var& result, const bool isNegative)
+ {
+ String::CharPointerType oldT (t);
+
+ int64 intValue = t.getAndAdvance() - '0';
+ jassert (intValue >= 0 && intValue < 10);
+
+ for (;;)
+ {
+ String::CharPointerType previousChar (t);
+ const juce_wchar c = t.getAndAdvance();
+ const int digit = ((int) c) - '0';
+
+ if (isPositiveAndBelow (digit, 10))
+ {
+ intValue = intValue * 10 + digit;
+ continue;
+ }
+
+ if (c == 'e' || c == 'E' || c == '.')
+ {
+ t = oldT;
+ const double asDouble = CharacterFunctions::readDoubleValue (t);
+ result = isNegative ? -asDouble : asDouble;
+ return Result::ok();
+ }
+
+ if (CharacterFunctions::isWhitespace (c)
+ || c == ',' || c == '}' || c == ']' || c == 0)
+ {
+ t = previousChar;
+ break;
+ }
+
+ return createFail ("Syntax error in number", &oldT);
+ }
+
+ const int64 correctedValue = isNegative ? -intValue : intValue;
+
+ if ((intValue >> 31) != 0)
+ result = correctedValue;
+ else
+ result = (int) correctedValue;
+
+ return Result::ok();
+ }
+
+ static Result parseObject (String::CharPointerType& t, var& result)
+ {
+ DynamicObject* const resultObject = new DynamicObject();
+ result = resultObject;
+ NamedValueSet& resultProperties = resultObject->getProperties();
+
+ for (;;)
+ {
+ t = t.findEndOfWhitespace();
+
+ String::CharPointerType oldT (t);
+ const juce_wchar c = t.getAndAdvance();
+
+ if (c == '}')
+ break;
+
+ if (c == 0)
+ return createFail ("Unexpected end-of-input in object declaration");
+
+ if (c == '"')
+ {
+ var propertyNameVar;
+ Result r (parseString ('"', t, propertyNameVar));
+
+ if (r.failed())
+ return r;
+
+ const Identifier propertyName (propertyNameVar.toString());
+
+ if (propertyName.isValid())
+ {
+ t = t.findEndOfWhitespace();
+ oldT = t;
+
+ const juce_wchar c2 = t.getAndAdvance();
+ if (c2 != ':')
+ return createFail ("Expected ':', but found", &oldT);
+
+ resultProperties.set (propertyName, var());
+ var* propertyValue = resultProperties.getVarPointer (propertyName);
+
+ Result r2 (parseAny (t, *propertyValue));
+
+ if (r2.failed())
+ return r2;
+
+ t = t.findEndOfWhitespace();
+ oldT = t;
+
+ const juce_wchar nextChar = t.getAndAdvance();
+
+ if (nextChar == ',')
+ continue;
+
+ if (nextChar == '}')
+ break;
+ }
+ }
+
+ return createFail ("Expected object member declaration, but found", &oldT);
+ }
+
+ return Result::ok();
+ }
+
+ static Result parseArray (String::CharPointerType& t, var& result)
+ {
+ result = var (Array<var>());
+ Array<var>* const destArray = result.getArray();
+
+ for (;;)
+ {
+ t = t.findEndOfWhitespace();
+
+ String::CharPointerType oldT (t);
+ const juce_wchar c = t.getAndAdvance();
+
+ if (c == ']')
+ break;
+
+ if (c == 0)
+ return createFail ("Unexpected end-of-input in array declaration");
+
+ t = oldT;
+ destArray->add (var());
+ Result r (parseAny (t, destArray->getReference (destArray->size() - 1)));
+
+ if (r.failed())
+ return r;
+
+ t = t.findEndOfWhitespace();
+ oldT = t;
+
+ const juce_wchar nextChar = t.getAndAdvance();
+
+ if (nextChar == ',')
+ continue;
+
+ if (nextChar == ']')
+ break;
+
+ return createFail ("Expected object array item, but found", &oldT);
+ }
+
+ return Result::ok();
+ }
+};
+
+//==============================================================================
+class JSONFormatter
+{
+public:
+ static void write (OutputStream& out, const var& v,
+ const int indentLevel, const bool allOnOneLine)
+ {
+ if (v.isString())
+ {
+ out << '"';
+ writeString (out, v.toString().getCharPointer());
+ out << '"';
+ }
+ else if (v.isVoid())
+ {
+ out << "null";
+ }
+ else if (v.isUndefined())
+ {
+ out << "undefined";
+ }
+ else if (v.isBool())
+ {
+ out << (static_cast<bool> (v) ? "true" : "false");
+ }
+ else if (v.isArray())
+ {
+ writeArray (out, *v.getArray(), indentLevel, allOnOneLine);
+ }
+ else if (v.isObject())
+ {
+ if (DynamicObject* object = v.getDynamicObject())
+ object->writeAsJSON (out, indentLevel, allOnOneLine);
+ else
+ jassertfalse; // Only DynamicObjects can be converted to JSON!
+ }
+ else
+ {
+ // Can't convert these other types of object to JSON!
+ jassert (! (v.isMethod() || v.isBinaryData()));
+
+ out << v.toString();
+ }
+ }
+
+ static void writeEscapedChar (OutputStream& out, const unsigned short value)
+ {
+ out << "\\u" << String::toHexString ((int) value).paddedLeft ('0', 4);
+ }
+
+ static void writeString (OutputStream& out, String::CharPointerType t)
+ {
+ for (;;)
+ {
+ const juce_wchar c (t.getAndAdvance());
+
+ switch (c)
+ {
+ case 0: return;
+
+ case '\"': out << "\\\""; break;
+ case '\\': out << "\\\\"; break;
+ case '\a': out << "\\a"; break;
+ case '\b': out << "\\b"; break;
+ case '\f': out << "\\f"; break;
+ case '\t': out << "\\t"; break;
+ case '\r': out << "\\r"; break;
+ case '\n': out << "\\n"; break;
+
+ default:
+ if (c >= 32 && c < 127)
+ {
+ out << (char) c;
+ }
+ else
+ {
+ if (CharPointer_UTF16::getBytesRequiredFor (c) > 2)
+ {
+ CharPointer_UTF16::CharType chars[2];
+ CharPointer_UTF16 utf16 (chars);
+ utf16.write (c);
+
+ for (int i = 0; i < 2; ++i)
+ writeEscapedChar (out, (unsigned short) chars[i]);
+ }
+ else
+ {
+ writeEscapedChar (out, (unsigned short) c);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ static void writeSpaces (OutputStream& out, int numSpaces)
+ {
+ out.writeRepeatedByte (' ', (size_t) numSpaces);
+ }
+
+ static void writeArray (OutputStream& out, const Array<var>& array,
+ const int indentLevel, const bool allOnOneLine)
+ {
+ out << '[';
+
+ if (array.size() > 0)
+ {
+ if (! allOnOneLine)
+ out << newLine;
+
+ for (int i = 0; i < array.size(); ++i)
+ {
+ if (! allOnOneLine)
+ writeSpaces (out, indentLevel + indentSize);
+
+ write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
+
+ if (i < array.size() - 1)
+ {
+ if (allOnOneLine)
+ out << ", ";
+ else
+ out << ',' << newLine;
+ }
+ else if (! allOnOneLine)
+ out << newLine;
+ }
+
+ if (! allOnOneLine)
+ writeSpaces (out, indentLevel);
+ }
+
+ out << ']';
+ }
+
+ enum { indentSize = 2 };
+};
+
+//==============================================================================
+var JSON::parse (const String& text)
+{
+ var result;
+
+ if (! parse (text, result))
+ result = var();
+
+ return result;
+}
+
+var JSON::fromString (StringRef text)
+{
+ var result;
+
+ if (! JSONParser::parseAny (text.text, result))
+ result = var();
+
+ return result;
+}
+
+var JSON::parse (InputStream& input)
+{
+ return parse (input.readEntireStreamAsString());
+}
+
+var JSON::parse (const File& file)
+{
+ return parse (file.loadFileAsString());
+}
+
+Result JSON::parse (const String& text, var& result)
+{
+ return JSONParser::parseObjectOrArray (text.getCharPointer(), result);
+}
+
+String JSON::toString (const var& data, const bool allOnOneLine)
+{
+ MemoryOutputStream mo (1024);
+ JSONFormatter::write (mo, data, 0, allOnOneLine);
+ return mo.toUTF8();
+}
+
+void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine)
+{
+ JSONFormatter::write (output, data, 0, allOnOneLine);
+}
+
+String JSON::escapeString (StringRef s)
+{
+ MemoryOutputStream mo;
+ JSONFormatter::writeString (mo, s.text);
+ return mo.toString();
+}
+
+Result JSON::parseQuotedString (String::CharPointerType& t, var& result)
+{
+ const juce_wchar quote = t.getAndAdvance();
+
+ if (quote == '"' || quote == '\'')
+ return JSONParser::parseString (quote, t, result);
+
+ return Result::fail ("Not a quoted string!");
+}
+
+//==============================================================================
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class JSONTests : public UnitTest
+{
+public:
+ JSONTests() : UnitTest ("JSON") {}
+
+ static String createRandomWideCharString (Random& r)
+ {
+ juce_wchar buffer[40] = { 0 };
+
+ for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
+ {
+ if (r.nextBool())
+ {
+ do
+ {
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
+ }
+ while (! CharPointer_UTF16::canRepresent (buffer[i]));
+ }
+ else
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
+ }
+
+ return CharPointer_UTF32 (buffer);
+ }
+
+ static String createRandomIdentifier (Random& r)
+ {
+ char buffer[30] = { 0 };
+
+ for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
+ {
+ static const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
+ buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
+ }
+
+ return CharPointer_ASCII (buffer);
+ }
+
+ static var createRandomVar (Random& r, int depth)
+ {
+ switch (r.nextInt (depth > 3 ? 6 : 8))
+ {
+ case 0: return var();
+ case 1: return r.nextInt();
+ case 2: return r.nextInt64();
+ case 3: return r.nextBool();
+ case 4: return r.nextDouble();
+ case 5: return createRandomWideCharString (r);
+
+ case 6:
+ {
+ var v (createRandomVar (r, depth + 1));
+
+ for (int i = 1 + r.nextInt (30); --i >= 0;)
+ v.append (createRandomVar (r, depth + 1));
+
+ return v;
+ }
+
+ case 7:
+ {
+ DynamicObject* o = new DynamicObject();
+
+ for (int i = r.nextInt (30); --i >= 0;)
+ o->setProperty (createRandomIdentifier (r), createRandomVar (r, depth + 1));
+
+ return o;
+ }
+
+ default:
+ return var();
+ }
+ }
+
+ void runTest()
+ {
+ beginTest ("JSON");
+ Random r = getRandom();
+
+ expect (JSON::parse (String::empty) == var::null);
+ expect (JSON::parse ("{}").isObject());
+ expect (JSON::parse ("[]").isArray());
+ expect (JSON::parse ("[ 1234 ]")[0].isInt());
+ expect (JSON::parse ("[ 12345678901234 ]")[0].isInt64());
+ expect (JSON::parse ("[ 1.123e3 ]")[0].isDouble());
+ expect (JSON::parse ("[ -1234]")[0].isInt());
+ expect (JSON::parse ("[-12345678901234]")[0].isInt64());
+ expect (JSON::parse ("[-1.123e3]")[0].isDouble());
+
+ for (int i = 100; --i >= 0;)
+ {
+ var v;
+
+ if (i > 0)
+ v = createRandomVar (r, 0);
+
+ const bool oneLine = r.nextBool();
+ String asString (JSON::toString (v, oneLine));
+ var parsed = JSON::parse ("[" + asString + "]")[0];
+ String parsedString (JSON::toString (parsed, oneLine));
+ expect (asString.isNotEmpty() && parsedString == asString);
+ }
+ }
+};
+
+static JSONTests JSONUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.h b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.h
new file mode 100644
index 0000000..7fb17ee
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_JSON.h
@@ -0,0 +1,136 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_JSON_H_INCLUDED
+#define JUCE_JSON_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Contains static methods for converting JSON-formatted text to and from var objects.
+
+ The var class is structurally compatible with JSON-formatted data, so these
+ functions allow you to parse JSON into a var object, and to convert a var
+ object to JSON-formatted text.
+
+ @see var
+*/
+class JUCE_API JSON
+{
+public:
+ //==============================================================================
+ /** Parses a string of JSON-formatted text, and returns a result code containing
+ any parse errors.
+
+ This will return the parsed structure in the parsedResult parameter, and will
+ return a Result object to indicate whether parsing was successful, and if not,
+ it will contain an error message.
+
+ If you're not interested in the error message, you can use one of the other
+ shortcut parse methods, which simply return a var::null if the parsing fails.
+
+ Note that this will only parse valid JSON, which means that the item given must
+ be either an object or an array definition. If you want to also be able to parse
+ any kind of primitive JSON object, use the fromString() method.
+ */
+ static Result parse (const String& text, var& parsedResult);
+
+ /** Attempts to parse some JSON-formatted text, and returns the result as a var object.
+
+ If the parsing fails, this simply returns var::null - if you need to find out more
+ detail about the parse error, use the alternative parse() method which returns a Result.
+
+ Note that this will only parse valid JSON, which means that the item given must
+ be either an object or an array definition. If you want to also be able to parse
+ any kind of primitive JSON object, use the fromString() method.
+ */
+ static var parse (const String& text);
+
+ /** Attempts to parse some JSON-formatted text from a file, and returns the result
+ as a var object.
+
+ Note that this is just a short-cut for reading the entire file into a string and
+ parsing the result.
+
+ If the parsing fails, this simply returns var::null - if you need to find out more
+ detail about the parse error, use the alternative parse() method which returns a Result.
+ */
+ static var parse (const File& file);
+
+ /** Attempts to parse some JSON-formatted text from a stream, and returns the result
+ as a var object.
+
+ Note that this is just a short-cut for reading the entire stream into a string and
+ parsing the result.
+
+ If the parsing fails, this simply returns var::null - if you need to find out more
+ detail about the parse error, use the alternative parse() method which returns a Result.
+ */
+ static var parse (InputStream& input);
+
+ //==============================================================================
+ /** Returns a string which contains a JSON-formatted representation of the var object.
+ If allOnOneLine is true, the result will be compacted into a single line of text
+ with no carriage-returns. If false, it will be laid-out in a more human-readable format.
+ @see writeToStream
+ */
+ static String toString (const var& objectToFormat,
+ bool allOnOneLine = false);
+
+ /** Parses a string that was created with the toString() method.
+ This is slightly different to the parse() methods because they will reject primitive
+ values and only accept array or object definitions, whereas this method will handle
+ either.
+ */
+ static var fromString (StringRef);
+
+ /** Writes a JSON-formatted representation of the var object to the given stream.
+ If allOnOneLine is true, the result will be compacted into a single line of text
+ with no carriage-returns. If false, it will be laid-out in a more human-readable format.
+ @see toString
+ */
+ static void writeToStream (OutputStream& output,
+ const var& objectToFormat,
+ bool allOnOneLine = false);
+
+ /** Returns a version of a string with any extended characters escaped. */
+ static String escapeString (StringRef);
+
+ /** Parses a quoted string-literal in JSON format, returning the un-escaped result in the
+ result parameter, and an error message in case the content was illegal.
+ This advances the text parameter, leaving it positioned after the closing quote.
+ */
+ static Result parseQuotedString (String::CharPointerType& text, var& result);
+
+private:
+ //==============================================================================
+ JSON() JUCE_DELETED_FUNCTION; // This class can't be instantiated - just use its static methods.
+};
+
+
+#endif // JUCE_JSON_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.cpp
new file mode 100644
index 0000000..af99a84
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.cpp
@@ -0,0 +1,1710 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#define JUCE_JS_OPERATORS(X) \
+ X(semicolon, ";") X(dot, ".") X(comma, ",") \
+ X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
+ X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
+ X(typeEquals, "===") X(equals, "==") X(assign, "=") \
+ X(typeNotEquals, "!==") X(notEquals, "!=") X(logicalNot, "!") \
+ X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
+ X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
+ X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
+ X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") \
+ X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
+ X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
+ X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
+ X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
+
+#define JUCE_JS_KEYWORDS(X) \
+ X(var, "var") X(if_, "if") X(else_, "else") X(do_, "do") X(null_, "null") \
+ X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") X(undefined, "undefined") \
+ X(function, "function") X(return_, "return") X(true_, "true") X(false_, "false") X(new_, "new")
+
+namespace TokenTypes
+{
+ #define JUCE_DECLARE_JS_TOKEN(name, str) static const char* const name = str;
+ JUCE_JS_KEYWORDS (JUCE_DECLARE_JS_TOKEN)
+ JUCE_JS_OPERATORS (JUCE_DECLARE_JS_TOKEN)
+ JUCE_DECLARE_JS_TOKEN (eof, "$eof")
+ JUCE_DECLARE_JS_TOKEN (literal, "$literal")
+ JUCE_DECLARE_JS_TOKEN (identifier, "$identifier")
+}
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4702)
+#endif
+
+//==============================================================================
+struct JavascriptEngine::RootObject : public DynamicObject
+{
+ RootObject()
+ {
+ setMethod ("exec", exec);
+ setMethod ("eval", eval);
+ setMethod ("trace", trace);
+ setMethod ("charToInt", charToInt);
+ setMethod ("parseInt", IntegerClass::parseInt);
+ }
+
+ Time timeout;
+
+ typedef const var::NativeFunctionArgs& Args;
+ typedef const char* TokenType;
+
+ void execute (const String& code)
+ {
+ ExpressionTreeBuilder tb (code);
+ ScopedPointer<BlockStatement> (tb.parseStatementList())->perform (Scope (nullptr, this, this), nullptr);
+ }
+
+ var evaluate (const String& code)
+ {
+ ExpressionTreeBuilder tb (code);
+ return ExpPtr (tb.parseExpression())->getResult (Scope (nullptr, this, this));
+ }
+
+ //==============================================================================
+ static bool areTypeEqual (const var& a, const var& b)
+ {
+ return a.hasSameTypeAs (b) && isFunction (a) == isFunction (b)
+ && (((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid())) || a == b);
+ }
+
+ static String getTokenName (TokenType t) { return t[0] == '$' ? String (t + 1) : ("'" + String (t) + "'"); }
+ static bool isFunction (const var& v) { return dynamic_cast<FunctionObject*> (v.getObject()) != nullptr; }
+ static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); }
+ static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); }
+ static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; }
+
+ //==============================================================================
+ struct CodeLocation
+ {
+ CodeLocation (const String& code) noexcept : program (code), location (program.getCharPointer()) {}
+ CodeLocation (const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
+
+ void throwError (const String& message) const
+ {
+ int col = 1, line = 1;
+
+ for (String::CharPointerType i (program.getCharPointer()); i < location && ! i.isEmpty(); ++i)
+ {
+ ++col;
+ if (*i == '\n') { col = 1; ++line; }
+ }
+
+ throw "Line " + String (line) + ", column " + String (col) + " : " + message;
+ }
+
+ String program;
+ String::CharPointerType location;
+ };
+
+ //==============================================================================
+ struct Scope
+ {
+ Scope (const Scope* p, RootObject* r, DynamicObject* s) noexcept : parent (p), root (r), scope (s) {}
+
+ const Scope* parent;
+ ReferenceCountedObjectPtr<RootObject> root;
+ DynamicObject::Ptr scope;
+
+ var findFunctionCall (const CodeLocation& location, const var& targetObject, Identifier functionName) const
+ {
+ if (DynamicObject* o = targetObject.getDynamicObject())
+ {
+ if (var* prop = o->getProperties().getVarPointer (functionName))
+ return *prop;
+
+ for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr;
+ p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
+ {
+ if (var* prop = p->getProperties().getVarPointer (functionName))
+ return *prop;
+ }
+ }
+
+ if (targetObject.isString())
+ if (var* m = findRootClassProperty (StringClass::getClassName(), functionName))
+ return *m;
+
+ if (targetObject.isArray())
+ if (var* m = findRootClassProperty (ArrayClass::getClassName(), functionName))
+ return *m;
+
+ if (var* m = findRootClassProperty (ObjectClass::getClassName(), functionName))
+ return *m;
+
+ location.throwError ("Unknown function '" + functionName.toString() + "'");
+ return var();
+ }
+
+ var* findRootClassProperty (Identifier className, Identifier propName) const
+ {
+ if (DynamicObject* cls = root->getProperty (className).getDynamicObject())
+ return cls->getProperties().getVarPointer (propName);
+
+ return nullptr;
+ }
+
+ var findSymbolInParentScopes (Identifier name) const
+ {
+ if (var* v = scope->getProperties().getVarPointer (name))
+ return *v;
+
+ return parent != nullptr ? parent->findSymbolInParentScopes (name)
+ : var::undefined();
+ }
+
+ bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const
+ {
+ const NamedValueSet& props = scope->getProperties();
+
+ DynamicObject* target = args.thisObject.getDynamicObject();
+
+ if (target == nullptr || target == scope)
+ {
+ if (const var* m = props.getVarPointer (function))
+ {
+ if (FunctionObject* fo = dynamic_cast<FunctionObject*> (m->getObject()))
+ {
+ result = fo->invoke (*this, args);
+ return true;
+ }
+ }
+ }
+
+ for (int i = 0; i < props.size(); ++i)
+ if (DynamicObject* o = props.getValueAt (i).getDynamicObject())
+ if (Scope (this, root, o).findAndInvokeMethod (function, args, result))
+ return true;
+
+ return false;
+ }
+
+ void checkTimeOut (const CodeLocation& location) const
+ {
+ if (Time::getCurrentTime() > root->timeout)
+ location.throwError ("Execution timed-out");
+ }
+ };
+
+ //==============================================================================
+ struct Statement
+ {
+ Statement (const CodeLocation& l) noexcept : location (l) {}
+ virtual ~Statement() {}
+
+ enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
+ virtual ResultCode perform (const Scope&, var*) const { return ok; }
+
+ CodeLocation location;
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Statement)
+ };
+
+ struct Expression : public Statement
+ {
+ Expression (const CodeLocation& l) noexcept : Statement (l) {}
+
+ virtual var getResult (const Scope&) const { return var::undefined(); }
+ virtual void assign (const Scope&, const var&) const { location.throwError ("Cannot assign to this expression!"); }
+
+ ResultCode perform (const Scope& s, var*) const override { getResult (s); return ok; }
+ };
+
+ typedef ScopedPointer<Expression> ExpPtr;
+
+ struct BlockStatement : public Statement
+ {
+ BlockStatement (const CodeLocation& l) noexcept : Statement (l) {}
+
+ ResultCode perform (const Scope& s, var* returnedValue) const override
+ {
+ for (int i = 0; i < statements.size(); ++i)
+ if (ResultCode r = statements.getUnchecked(i)->perform (s, returnedValue))
+ return r;
+
+ return ok;
+ }
+
+ OwnedArray<Statement> statements;
+ };
+
+ struct IfStatement : public Statement
+ {
+ IfStatement (const CodeLocation& l) noexcept : Statement (l) {}
+
+ ResultCode perform (const Scope& s, var* returnedValue) const override
+ {
+ return (condition->getResult(s) ? trueBranch : falseBranch)->perform (s, returnedValue);
+ }
+
+ ExpPtr condition;
+ ScopedPointer<Statement> trueBranch, falseBranch;
+ };
+
+ struct VarStatement : public Statement
+ {
+ VarStatement (const CodeLocation& l) noexcept : Statement (l) {}
+
+ ResultCode perform (const Scope& s, var*) const override
+ {
+ s.scope->setProperty (name, initialiser->getResult (s));
+ return ok;
+ }
+
+ Identifier name;
+ ExpPtr initialiser;
+ };
+
+ struct LoopStatement : public Statement
+ {
+ LoopStatement (const CodeLocation& l, bool isDo) noexcept : Statement (l), isDoLoop (isDo) {}
+
+ ResultCode perform (const Scope& s, var* returnedValue) const override
+ {
+ initialiser->perform (s, nullptr);
+
+ while (isDoLoop || condition->getResult (s))
+ {
+ s.checkTimeOut (location);
+ ResultCode r = body->perform (s, returnedValue);
+
+ if (r == returnWasHit) return r;
+ if (r == breakWasHit) break;
+
+ iterator->perform (s, nullptr);
+
+ if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
+ break;
+ }
+
+ return ok;
+ }
+
+ ScopedPointer<Statement> initialiser, iterator, body;
+ ExpPtr condition;
+ bool isDoLoop;
+ };
+
+ struct ReturnStatement : public Statement
+ {
+ ReturnStatement (const CodeLocation& l, Expression* v) noexcept : Statement (l), returnValue (v) {}
+
+ ResultCode perform (const Scope& s, var* ret) const override
+ {
+ if (ret != nullptr) *ret = returnValue->getResult (s);
+ return returnWasHit;
+ }
+
+ ExpPtr returnValue;
+ };
+
+ struct BreakStatement : public Statement
+ {
+ BreakStatement (const CodeLocation& l) noexcept : Statement (l) {}
+ ResultCode perform (const Scope&, var*) const override { return breakWasHit; }
+ };
+
+ struct ContinueStatement : public Statement
+ {
+ ContinueStatement (const CodeLocation& l) noexcept : Statement (l) {}
+ ResultCode perform (const Scope&, var*) const override { return continueWasHit; }
+ };
+
+ struct LiteralValue : public Expression
+ {
+ LiteralValue (const CodeLocation& l, const var& v) noexcept : Expression (l), value (v) {}
+ var getResult (const Scope&) const override { return value; }
+ var value;
+ };
+
+ struct UnqualifiedName : public Expression
+ {
+ UnqualifiedName (const CodeLocation& l, Identifier n) noexcept : Expression (l), name (n) {}
+
+ var getResult (const Scope& s) const override { return s.findSymbolInParentScopes (name); }
+
+ void assign (const Scope& s, const var& newValue) const override
+ {
+ if (var* v = s.scope->getProperties().getVarPointer (name))
+ *v = newValue;
+ else
+ s.root->setProperty (name, newValue);
+ }
+
+ Identifier name;
+ };
+
+ struct DotOperator : public Expression
+ {
+ DotOperator (const CodeLocation& l, ExpPtr& p, Identifier c) noexcept : Expression (l), parent (p), child (c) {}
+
+ var getResult (const Scope& s) const override
+ {
+ var p (parent->getResult (s));
+ static const Identifier lengthID ("length");
+
+ if (child == lengthID)
+ {
+ if (Array<var>* array = p.getArray()) return array->size();
+ if (p.isString()) return p.toString().length();
+ }
+
+ if (DynamicObject* o = p.getDynamicObject())
+ if (var* v = o->getProperties().getVarPointer (child))
+ return *v;
+
+ return var::undefined();
+ }
+
+ void assign (const Scope& s, const var& newValue) const override
+ {
+ if (DynamicObject* o = parent->getResult (s).getDynamicObject())
+ o->setProperty (child, newValue);
+ else
+ Expression::assign (s, newValue);
+ }
+
+ ExpPtr parent;
+ Identifier child;
+ };
+
+ struct ArraySubscript : public Expression
+ {
+ ArraySubscript (const CodeLocation& l) noexcept : Expression (l) {}
+
+ var getResult (const Scope& s) const override
+ {
+ if (const Array<var>* array = object->getResult (s).getArray())
+ return (*array) [static_cast<int> (index->getResult (s))];
+
+ return var::undefined();
+ }
+
+ void assign (const Scope& s, const var& newValue) const override
+ {
+ if (Array<var>* array = object->getResult (s).getArray())
+ {
+ const int i = index->getResult (s);
+ while (array->size() < i)
+ array->add (var::undefined());
+
+ array->set (i, newValue);
+ return;
+ }
+
+ Expression::assign (s, newValue);
+ }
+
+ ExpPtr object, index;
+ };
+
+ struct BinaryOperatorBase : public Expression
+ {
+ BinaryOperatorBase (const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
+ : Expression (l), lhs (a), rhs (b), operation (op) {}
+
+ ExpPtr lhs, rhs;
+ TokenType operation;
+ };
+
+ struct BinaryOperator : public BinaryOperatorBase
+ {
+ BinaryOperator (const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
+ : BinaryOperatorBase (l, a, b, op) {}
+
+ virtual var getWithUndefinedArg() const { return var::undefined(); }
+ virtual var getWithDoubles (double, double) const { return throwError ("Double"); }
+ virtual var getWithInts (int64, int64) const { return throwError ("Integer"); }
+ virtual var getWithArrayOrObject (const var& a, const var&) const { return throwError (a.isArray() ? "Array" : "Object"); }
+ virtual var getWithStrings (const String&, const String&) const { return throwError ("String"); }
+
+ var getResult (const Scope& s) const override
+ {
+ var a (lhs->getResult (s)), b (rhs->getResult (s));
+
+ if ((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid()))
+ return getWithUndefinedArg();
+
+ if (isNumericOrUndefined (a) && isNumericOrUndefined (b))
+ return (a.isDouble() || b.isDouble()) ? getWithDoubles (a, b) : getWithInts (a, b);
+
+ if (a.isArray() || a.isObject())
+ return getWithArrayOrObject (a, b);
+
+ return getWithStrings (a.toString(), b.toString());
+ }
+
+ var throwError (const char* typeName) const
+ { location.throwError (getTokenName (operation) + " is not allowed on the " + typeName + " type"); return var(); }
+ };
+
+ struct EqualsOp : public BinaryOperator
+ {
+ EqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {}
+ var getWithUndefinedArg() const override { return true; }
+ var getWithDoubles (double a, double b) const override { return a == b; }
+ var getWithInts (int64 a, int64 b) const override { return a == b; }
+ var getWithStrings (const String& a, const String& b) const override { return a == b; }
+ var getWithArrayOrObject (const var& a, const var& b) const override { return a == b; }
+ };
+
+ struct NotEqualsOp : public BinaryOperator
+ {
+ NotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {}
+ var getWithUndefinedArg() const override { return false; }
+ var getWithDoubles (double a, double b) const override { return a != b; }
+ var getWithInts (int64 a, int64 b) const override { return a != b; }
+ var getWithStrings (const String& a, const String& b) const override { return a != b; }
+ var getWithArrayOrObject (const var& a, const var& b) const override { return a != b; }
+ };
+
+ struct LessThanOp : public BinaryOperator
+ {
+ LessThanOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThan) {}
+ var getWithDoubles (double a, double b) const override { return a < b; }
+ var getWithInts (int64 a, int64 b) const override { return a < b; }
+ var getWithStrings (const String& a, const String& b) const override { return a < b; }
+ };
+
+ struct LessThanOrEqualOp : public BinaryOperator
+ {
+ LessThanOrEqualOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThanOrEqual) {}
+ var getWithDoubles (double a, double b) const override { return a <= b; }
+ var getWithInts (int64 a, int64 b) const override { return a <= b; }
+ var getWithStrings (const String& a, const String& b) const override { return a <= b; }
+ };
+
+ struct GreaterThanOp : public BinaryOperator
+ {
+ GreaterThanOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThan) {}
+ var getWithDoubles (double a, double b) const override { return a > b; }
+ var getWithInts (int64 a, int64 b) const override { return a > b; }
+ var getWithStrings (const String& a, const String& b) const override { return a > b; }
+ };
+
+ struct GreaterThanOrEqualOp : public BinaryOperator
+ {
+ GreaterThanOrEqualOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThanOrEqual) {}
+ var getWithDoubles (double a, double b) const override { return a >= b; }
+ var getWithInts (int64 a, int64 b) const override { return a >= b; }
+ var getWithStrings (const String& a, const String& b) const override { return a >= b; }
+ };
+
+ struct AdditionOp : public BinaryOperator
+ {
+ AdditionOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::plus) {}
+ var getWithDoubles (double a, double b) const override { return a + b; }
+ var getWithInts (int64 a, int64 b) const override { return a + b; }
+ var getWithStrings (const String& a, const String& b) const override { return a + b; }
+ };
+
+ struct SubtractionOp : public BinaryOperator
+ {
+ SubtractionOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::minus) {}
+ var getWithDoubles (double a, double b) const override { return a - b; }
+ var getWithInts (int64 a, int64 b) const override { return a - b; }
+ };
+
+ struct MultiplyOp : public BinaryOperator
+ {
+ MultiplyOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::times) {}
+ var getWithDoubles (double a, double b) const override { return a * b; }
+ var getWithInts (int64 a, int64 b) const override { return a * b; }
+ };
+
+ struct DivideOp : public BinaryOperator
+ {
+ DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {}
+ var getWithDoubles (double a, double b) const override { return b != 0 ? a / b : std::numeric_limits<double>::infinity(); }
+ var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a / b) : var (std::numeric_limits<double>::infinity()); }
+ };
+
+ struct ModuloOp : public BinaryOperator
+ {
+ ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {}
+ var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); }
+ };
+
+ struct BitwiseOrOp : public BinaryOperator
+ {
+ BitwiseOrOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseOr) {}
+ var getWithInts (int64 a, int64 b) const override { return a | b; }
+ };
+
+ struct BitwiseAndOp : public BinaryOperator
+ {
+ BitwiseAndOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseAnd) {}
+ var getWithInts (int64 a, int64 b) const override { return a & b; }
+ };
+
+ struct BitwiseXorOp : public BinaryOperator
+ {
+ BitwiseXorOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseXor) {}
+ var getWithInts (int64 a, int64 b) const override { return a ^ b; }
+ };
+
+ struct LeftShiftOp : public BinaryOperator
+ {
+ LeftShiftOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::leftShift) {}
+ var getWithInts (int64 a, int64 b) const override { return ((int) a) << (int) b; }
+ };
+
+ struct RightShiftOp : public BinaryOperator
+ {
+ RightShiftOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShift) {}
+ var getWithInts (int64 a, int64 b) const override { return ((int) a) >> (int) b; }
+ };
+
+ struct RightShiftUnsignedOp : public BinaryOperator
+ {
+ RightShiftUnsignedOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShiftUnsigned) {}
+ var getWithInts (int64 a, int64 b) const override { return (int) (((uint32) a) >> (int) b); }
+ };
+
+ struct LogicalAndOp : public BinaryOperatorBase
+ {
+ LogicalAndOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalAnd) {}
+ var getResult (const Scope& s) const override { return lhs->getResult (s) && rhs->getResult (s); }
+ };
+
+ struct LogicalOrOp : public BinaryOperatorBase
+ {
+ LogicalOrOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalOr) {}
+ var getResult (const Scope& s) const override { return lhs->getResult (s) || rhs->getResult (s); }
+ };
+
+ struct TypeEqualsOp : public BinaryOperatorBase
+ {
+ TypeEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeEquals) {}
+ var getResult (const Scope& s) const override { return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
+ };
+
+ struct TypeNotEqualsOp : public BinaryOperatorBase
+ {
+ TypeNotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeNotEquals) {}
+ var getResult (const Scope& s) const override { return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
+ };
+
+ struct ConditionalOp : public Expression
+ {
+ ConditionalOp (const CodeLocation& l) noexcept : Expression (l) {}
+
+ var getResult (const Scope& s) const override { return (condition->getResult (s) ? trueBranch : falseBranch)->getResult (s); }
+ void assign (const Scope& s, const var& v) const override { (condition->getResult (s) ? trueBranch : falseBranch)->assign (s, v); }
+
+ ExpPtr condition, trueBranch, falseBranch;
+ };
+
+ struct Assignment : public Expression
+ {
+ Assignment (const CodeLocation& l, ExpPtr& dest, ExpPtr& source) noexcept : Expression (l), target (dest), newValue (source) {}
+
+ var getResult (const Scope& s) const override
+ {
+ var value (newValue->getResult (s));
+ target->assign (s, value);
+ return value;
+ }
+
+ ExpPtr target, newValue;
+ };
+
+ struct SelfAssignment : public Expression
+ {
+ SelfAssignment (const CodeLocation& l, Expression* dest, Expression* source) noexcept
+ : Expression (l), target (dest), newValue (source) {}
+
+ var getResult (const Scope& s) const override
+ {
+ var value (newValue->getResult (s));
+ target->assign (s, value);
+ return value;
+ }
+
+ Expression* target; // Careful! this pointer aliases a sub-term of newValue!
+ ExpPtr newValue;
+ TokenType op;
+ };
+
+ struct PostAssignment : public SelfAssignment
+ {
+ PostAssignment (const CodeLocation& l, Expression* dest, Expression* source) noexcept : SelfAssignment (l, dest, source) {}
+
+ var getResult (const Scope& s) const override
+ {
+ var oldValue (target->getResult (s));
+ target->assign (s, newValue->getResult (s));
+ return oldValue;
+ }
+ };
+
+ struct FunctionCall : public Expression
+ {
+ FunctionCall (const CodeLocation& l) noexcept : Expression (l) {}
+
+ var getResult (const Scope& s) const override
+ {
+ if (DotOperator* dot = dynamic_cast<DotOperator*> (object.get()))
+ {
+ var thisObject (dot->parent->getResult (s));
+ return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject);
+ }
+
+ var function (object->getResult (s));
+ return invokeFunction (s, function, var (s.scope));
+ }
+
+ var invokeFunction (const Scope& s, const var& function, const var& thisObject) const
+ {
+ s.checkTimeOut (location);
+
+ Array<var> argVars;
+ for (int i = 0; i < arguments.size(); ++i)
+ argVars.add (arguments.getUnchecked(i)->getResult (s));
+
+ const var::NativeFunctionArgs args (thisObject, argVars.begin(), argVars.size());
+
+ if (var::NativeFunction nativeFunction = function.getNativeFunction())
+ return nativeFunction (args);
+
+ if (FunctionObject* fo = dynamic_cast<FunctionObject*> (function.getObject()))
+ return fo->invoke (s, args);
+
+ location.throwError ("This expression is not a function!"); return var();
+ }
+
+ ExpPtr object;
+ OwnedArray<Expression> arguments;
+ };
+
+ struct NewOperator : public FunctionCall
+ {
+ NewOperator (const CodeLocation& l) noexcept : FunctionCall (l) {}
+
+ var getResult (const Scope& s) const override
+ {
+ var classOrFunc = object->getResult (s);
+
+ const bool isFunc = isFunction (classOrFunc);
+ if (! (isFunc || classOrFunc.getDynamicObject() != nullptr))
+ return var::undefined();
+
+ DynamicObject::Ptr newObject (new DynamicObject());
+
+ if (isFunc)
+ invokeFunction (s, classOrFunc, newObject.get());
+ else
+ newObject->setProperty (getPrototypeIdentifier(), classOrFunc);
+
+ return newObject.get();
+ }
+ };
+
+ struct ObjectDeclaration : public Expression
+ {
+ ObjectDeclaration (const CodeLocation& l) noexcept : Expression (l) {}
+
+ var getResult (const Scope& s) const override
+ {
+ DynamicObject::Ptr newObject (new DynamicObject());
+
+ for (int i = 0; i < names.size(); ++i)
+ newObject->setProperty (names.getUnchecked(i), initialisers.getUnchecked(i)->getResult (s));
+
+ return newObject.get();
+ }
+
+ Array<Identifier> names;
+ OwnedArray<Expression> initialisers;
+ };
+
+ struct ArrayDeclaration : public Expression
+ {
+ ArrayDeclaration (const CodeLocation& l) noexcept : Expression (l) {}
+
+ var getResult (const Scope& s) const override
+ {
+ Array<var> a;
+
+ for (int i = 0; i < values.size(); ++i)
+ a.add (values.getUnchecked(i)->getResult (s));
+
+ return a;
+ }
+
+ OwnedArray<Expression> values;
+ };
+
+ //==============================================================================
+ struct FunctionObject : public DynamicObject
+ {
+ FunctionObject() noexcept {}
+
+ FunctionObject (const FunctionObject& other) : DynamicObject(), functionCode (other.functionCode)
+ {
+ ExpressionTreeBuilder tb (functionCode);
+ tb.parseFunctionParamsAndBody (*this);
+ }
+
+ DynamicObject::Ptr clone() override { return new FunctionObject (*this); }
+
+ void writeAsJSON (OutputStream& out, int /*indentLevel*/, bool /*allOnOneLine*/) override
+ {
+ out << "function " << functionCode;
+ }
+
+ var invoke (const Scope& s, const var::NativeFunctionArgs& args) const
+ {
+ DynamicObject::Ptr functionRoot (new DynamicObject());
+
+ static const Identifier thisIdent ("this");
+ functionRoot->setProperty (thisIdent, args.thisObject);
+
+ for (int i = 0; i < parameters.size(); ++i)
+ functionRoot->setProperty (parameters.getReference(i),
+ i < args.numArguments ? args.arguments[i] : var::undefined());
+
+ var result;
+ body->perform (Scope (&s, s.root, functionRoot), &result);
+ return result;
+ }
+
+ String functionCode;
+ Array<Identifier> parameters;
+ ScopedPointer<Statement> body;
+ };
+
+ //==============================================================================
+ struct TokenIterator
+ {
+ TokenIterator (const String& code) : location (code), p (code.getCharPointer()) { skip(); }
+
+ void skip()
+ {
+ skipWhitespaceAndComments();
+ location.location = p;
+ currentType = matchNextToken();
+ }
+
+ void match (TokenType expected)
+ {
+ if (currentType != expected)
+ location.throwError ("Found " + getTokenName (currentType) + " when expecting " + getTokenName (expected));
+
+ skip();
+ }
+
+ bool matchIf (TokenType expected) { if (currentType == expected) { skip(); return true; } return false; }
+ bool matchesAny (TokenType t1, TokenType t2) const { return currentType == t1 || currentType == t2; }
+ bool matchesAny (TokenType t1, TokenType t2, TokenType t3) const { return matchesAny (t1, t2) || currentType == t3; }
+
+ CodeLocation location;
+ TokenType currentType;
+ var currentValue;
+
+ private:
+ String::CharPointerType p;
+
+ static bool isIdentifierStart (const juce_wchar c) noexcept { return CharacterFunctions::isLetter (c) || c == '_'; }
+ static bool isIdentifierBody (const juce_wchar c) noexcept { return CharacterFunctions::isLetterOrDigit (c) || c == '_'; }
+
+ TokenType matchNextToken()
+ {
+ if (isIdentifierStart (*p))
+ {
+ String::CharPointerType end (p);
+ while (isIdentifierBody (*++end)) {}
+
+ const size_t len = (size_t) (end - p);
+ #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
+ JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
+
+ currentValue = String (p, end); p = end;
+ return TokenTypes::identifier;
+ }
+
+ if (p.isDigit())
+ {
+ if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
+ return TokenTypes::literal;
+
+ location.throwError ("Syntax error in numeric constant");
+ }
+
+ if (parseStringLiteral (*p) || (*p == '.' && parseFloatLiteral()))
+ return TokenTypes::literal;
+
+ #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
+ JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
+
+ if (! p.isEmpty())
+ location.throwError ("Unexpected character '" + String::charToString (*p) + "' in source");
+
+ return TokenTypes::eof;
+ }
+
+ bool matchToken (TokenType name, const size_t len) noexcept
+ {
+ if (p.compareUpTo (CharPointer_ASCII (name), (int) len) != 0) return false;
+ p += (int) len; return true;
+ }
+
+ void skipWhitespaceAndComments()
+ {
+ for (;;)
+ {
+ p = p.findEndOfWhitespace();
+
+ if (*p == '/')
+ {
+ const juce_wchar c2 = p[1];
+
+ if (c2 == '/') { p = CharacterFunctions::find (p, (juce_wchar) '\n'); continue; }
+
+ if (c2 == '*')
+ {
+ location.location = p;
+ p = CharacterFunctions::find (p + 2, CharPointer_ASCII ("*/"));
+ if (p.isEmpty()) location.throwError ("Unterminated '/*' comment");
+ p += 2; continue;
+ }
+ }
+
+ break;
+ }
+ }
+
+ bool parseStringLiteral (juce_wchar quoteType)
+ {
+ if (quoteType != '"' && quoteType != '\'')
+ return false;
+
+ Result r (JSON::parseQuotedString (p, currentValue));
+ if (r.failed()) location.throwError (r.getErrorMessage());
+ return true;
+ }
+
+ bool parseHexLiteral()
+ {
+ if (*p != '0' || (p[1] != 'x' && p[1] != 'X')) return false;
+
+ String::CharPointerType t (++p);
+ int64 v = CharacterFunctions::getHexDigitValue (*++t);
+ if (v < 0) return false;
+
+ for (;;)
+ {
+ const int digit = CharacterFunctions::getHexDigitValue (*++t);
+ if (digit < 0) break;
+ v = v * 16 + digit;
+ }
+
+ currentValue = v; p = t;
+ return true;
+ }
+
+ bool parseFloatLiteral()
+ {
+ int numDigits = 0;
+ String::CharPointerType t (p);
+ while (t.isDigit()) { ++t; ++numDigits; }
+
+ const bool hasPoint = (*t == '.');
+
+ if (hasPoint)
+ while ((++t).isDigit()) ++numDigits;
+
+ if (numDigits == 0)
+ return false;
+
+ juce_wchar c = *t;
+ const bool hasExponent = (c == 'e' || c == 'E');
+
+ if (hasExponent)
+ {
+ c = *++t;
+ if (c == '+' || c == '-') ++t;
+ if (! t.isDigit()) return false;
+ while ((++t).isDigit()) {}
+ }
+
+ if (! (hasExponent || hasPoint)) return false;
+
+ currentValue = CharacterFunctions::getDoubleValue (p); p = t;
+ return true;
+ }
+
+ bool parseOctalLiteral()
+ {
+ String::CharPointerType t (p);
+ int64 v = *t - '0';
+ if (v != 0) return false; // first digit of octal must be 0
+
+ for (;;)
+ {
+ const int digit = (int) (*++t - '0');
+ if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
+ else if (isPositiveAndBelow (digit, 10)) location.throwError ("Decimal digit in octal constant");
+ else break;
+ }
+
+ currentValue = v; p = t;
+ return true;
+ }
+
+ bool parseDecimalLiteral()
+ {
+ int64 v = 0;
+
+ for (;; ++p)
+ {
+ const int digit = (int) (*p - '0');
+ if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
+ else break;
+ }
+
+ currentValue = v;
+ return true;
+ }
+ };
+
+ //==============================================================================
+ struct ExpressionTreeBuilder : private TokenIterator
+ {
+ ExpressionTreeBuilder (const String code) : TokenIterator (code) {}
+
+ BlockStatement* parseStatementList()
+ {
+ ScopedPointer<BlockStatement> b (new BlockStatement (location));
+
+ while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
+ b->statements.add (parseStatement());
+
+ return b.release();
+ }
+
+ void parseFunctionParamsAndBody (FunctionObject& fo)
+ {
+ match (TokenTypes::openParen);
+
+ while (currentType != TokenTypes::closeParen)
+ {
+ fo.parameters.add (currentValue.toString());
+ match (TokenTypes::identifier);
+
+ if (currentType != TokenTypes::closeParen)
+ match (TokenTypes::comma);
+ }
+
+ match (TokenTypes::closeParen);
+ fo.body = parseBlock();
+ }
+
+ Expression* parseExpression()
+ {
+ ExpPtr lhs (parseLogicOperator());
+
+ if (matchIf (TokenTypes::question)) return parseTerneryOperator (lhs);
+ if (matchIf (TokenTypes::assign)) { ExpPtr rhs (parseExpression()); return new Assignment (location, lhs, rhs); }
+ if (matchIf (TokenTypes::plusEquals)) return parseInPlaceOpExpression<AdditionOp> (lhs);
+ if (matchIf (TokenTypes::minusEquals)) return parseInPlaceOpExpression<SubtractionOp> (lhs);
+ if (matchIf (TokenTypes::leftShiftEquals)) return parseInPlaceOpExpression<LeftShiftOp> (lhs);
+ if (matchIf (TokenTypes::rightShiftEquals)) return parseInPlaceOpExpression<RightShiftOp> (lhs);
+
+ return lhs.release();
+ }
+
+ private:
+ void throwError (const String& err) const { location.throwError (err); }
+
+ template <typename OpType>
+ Expression* parseInPlaceOpExpression (ExpPtr& lhs)
+ {
+ ExpPtr rhs (parseExpression());
+ Expression* bareLHS = lhs; // careful - bare pointer is deliberately alised
+ return new SelfAssignment (location, bareLHS, new OpType (location, lhs, rhs));
+ }
+
+ BlockStatement* parseBlock()
+ {
+ match (TokenTypes::openBrace);
+ ScopedPointer<BlockStatement> b (parseStatementList());
+ match (TokenTypes::closeBrace);
+ return b.release();
+ }
+
+ Statement* parseStatement()
+ {
+ if (currentType == TokenTypes::openBrace) return parseBlock();
+ if (matchIf (TokenTypes::var)) return parseVar();
+ if (matchIf (TokenTypes::if_)) return parseIf();
+ if (matchIf (TokenTypes::while_)) return parseDoOrWhileLoop (false);
+ if (matchIf (TokenTypes::do_)) return parseDoOrWhileLoop (true);
+ if (matchIf (TokenTypes::for_)) return parseForLoop();
+ if (matchIf (TokenTypes::return_)) return new ReturnStatement (location, matchIf (TokenTypes::semicolon) ? new Expression (location) : parseExpression());
+ if (matchIf (TokenTypes::break_)) return new BreakStatement (location);
+ if (matchIf (TokenTypes::continue_)) return new ContinueStatement (location);
+ if (matchIf (TokenTypes::function)) return parseFunction();
+ if (matchIf (TokenTypes::semicolon)) return new Statement (location);
+ if (matchIf (TokenTypes::plusplus)) return parsePreIncDec<AdditionOp>();
+ if (matchIf (TokenTypes::minusminus)) return parsePreIncDec<SubtractionOp>();
+
+ if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
+ return matchEndOfStatement (parseFactor());
+
+ if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
+ return matchEndOfStatement (parseExpression());
+
+ throwError ("Found " + getTokenName (currentType) + " when expecting a statement");
+ return nullptr;
+ }
+
+ Expression* matchEndOfStatement (Expression* ex) { ExpPtr e (ex); if (currentType != TokenTypes::eof) match (TokenTypes::semicolon); return e.release(); }
+ Expression* matchCloseParen (Expression* ex) { ExpPtr e (ex); match (TokenTypes::closeParen); return e.release(); }
+
+ Statement* parseIf()
+ {
+ ScopedPointer<IfStatement> s (new IfStatement (location));
+ match (TokenTypes::openParen);
+ s->condition = parseExpression();
+ match (TokenTypes::closeParen);
+ s->trueBranch = parseStatement();
+ s->falseBranch = matchIf (TokenTypes::else_) ? parseStatement() : new Statement (location);
+ return s.release();
+ }
+
+ Statement* parseVar()
+ {
+ ScopedPointer<VarStatement> s (new VarStatement (location));
+ s->name = parseIdentifier();
+ s->initialiser = matchIf (TokenTypes::assign) ? parseExpression() : new Expression (location);
+
+ if (matchIf (TokenTypes::comma))
+ {
+ ScopedPointer<BlockStatement> block (new BlockStatement (location));
+ block->statements.add (s.release());
+ block->statements.add (parseVar());
+ return block.release();
+ }
+
+ match (TokenTypes::semicolon);
+ return s.release();
+ }
+
+ Statement* parseFunction()
+ {
+ Identifier name;
+ var fn = parseFunctionDefinition (name);
+
+ if (name.isNull())
+ throwError ("Functions defined at statement-level must have a name");
+
+ ExpPtr nm (new UnqualifiedName (location, name)), value (new LiteralValue (location, fn));
+ return new Assignment (location, nm, value);
+ }
+
+ Statement* parseForLoop()
+ {
+ ScopedPointer<LoopStatement> s (new LoopStatement (location, false));
+ match (TokenTypes::openParen);
+ s->initialiser = parseStatement();
+
+ if (matchIf (TokenTypes::semicolon))
+ s->condition = new LiteralValue (location, true);
+ else
+ {
+ s->condition = parseExpression();
+ match (TokenTypes::semicolon);
+ }
+
+ s->iterator = parseExpression();
+ match (TokenTypes::closeParen);
+ s->body = parseStatement();
+ return s.release();
+ }
+
+ Statement* parseDoOrWhileLoop (bool isDoLoop)
+ {
+ ScopedPointer<LoopStatement> s (new LoopStatement (location, isDoLoop));
+ s->initialiser = new Statement (location);
+ s->iterator = new Statement (location);
+
+ if (isDoLoop)
+ {
+ s->body = parseBlock();
+ match (TokenTypes::while_);
+ }
+
+ match (TokenTypes::openParen);
+ s->condition = parseExpression();
+ match (TokenTypes::closeParen);
+
+ if (! isDoLoop)
+ s->body = parseStatement();
+
+ return s.release();
+ }
+
+ Identifier parseIdentifier()
+ {
+ Identifier i;
+ if (currentType == TokenTypes::identifier)
+ i = currentValue.toString();
+
+ match (TokenTypes::identifier);
+ return i;
+ }
+
+ var parseFunctionDefinition (Identifier& functionName)
+ {
+ const String::CharPointerType functionStart (location.location);
+
+ if (currentType == TokenTypes::identifier)
+ functionName = parseIdentifier();
+
+ ScopedPointer<FunctionObject> fo (new FunctionObject());
+ parseFunctionParamsAndBody (*fo);
+ fo->functionCode = String (functionStart, location.location);
+ return var (fo.release());
+ }
+
+ Expression* parseFunctionCall (FunctionCall* call, ExpPtr& function)
+ {
+ ScopedPointer<FunctionCall> s (call);
+ s->object = function;
+ match (TokenTypes::openParen);
+
+ while (currentType != TokenTypes::closeParen)
+ {
+ s->arguments.add (parseExpression());
+ if (currentType != TokenTypes::closeParen)
+ match (TokenTypes::comma);
+ }
+
+ return matchCloseParen (s.release());
+ }
+
+ Expression* parseSuffixes (Expression* e)
+ {
+ ExpPtr input (e);
+
+ if (matchIf (TokenTypes::dot))
+ return parseSuffixes (new DotOperator (location, input, parseIdentifier()));
+
+ if (currentType == TokenTypes::openParen)
+ return parseSuffixes (parseFunctionCall (new FunctionCall (location), input));
+
+ if (matchIf (TokenTypes::openBracket))
+ {
+ ScopedPointer<ArraySubscript> s (new ArraySubscript (location));
+ s->object = input;
+ s->index = parseExpression();
+ match (TokenTypes::closeBracket);
+ return parseSuffixes (s.release());
+ }
+
+ if (matchIf (TokenTypes::plusplus)) return parsePostIncDec<AdditionOp> (input);
+ if (matchIf (TokenTypes::minusminus)) return parsePostIncDec<SubtractionOp> (input);
+
+ return input.release();
+ }
+
+ Expression* parseFactor()
+ {
+ if (currentType == TokenTypes::identifier) return parseSuffixes (new UnqualifiedName (location, parseIdentifier()));
+ if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
+ if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1));
+ if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0));
+ if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var()));
+ if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location));
+
+ if (currentType == TokenTypes::literal)
+ {
+ var v (currentValue); skip();
+ return parseSuffixes (new LiteralValue (location, v));
+ }
+
+ if (matchIf (TokenTypes::openBrace))
+ {
+ ScopedPointer<ObjectDeclaration> e (new ObjectDeclaration (location));
+
+ while (currentType != TokenTypes::closeBrace)
+ {
+ e->names.add (currentValue.toString());
+ match ((currentType == TokenTypes::literal && currentValue.isString())
+ ? TokenTypes::literal : TokenTypes::identifier);
+ match (TokenTypes::colon);
+ e->initialisers.add (parseExpression());
+
+ if (currentType != TokenTypes::closeBrace)
+ match (TokenTypes::comma);
+ }
+
+ match (TokenTypes::closeBrace);
+ return parseSuffixes (e.release());
+ }
+
+ if (matchIf (TokenTypes::openBracket))
+ {
+ ScopedPointer<ArrayDeclaration> e (new ArrayDeclaration (location));
+
+ while (currentType != TokenTypes::closeBracket)
+ {
+ e->values.add (parseExpression());
+
+ if (currentType != TokenTypes::closeBracket)
+ match (TokenTypes::comma);
+ }
+
+ match (TokenTypes::closeBracket);
+ return parseSuffixes (e.release());
+ }
+
+ if (matchIf (TokenTypes::function))
+ {
+ Identifier name;
+ var fn = parseFunctionDefinition (name);
+
+ if (name.isValid())
+ throwError ("Inline functions definitions cannot have a name");
+
+ return new LiteralValue (location, fn);
+ }
+
+ if (matchIf (TokenTypes::new_))
+ {
+ ExpPtr name (new UnqualifiedName (location, parseIdentifier()));
+
+ while (matchIf (TokenTypes::dot))
+ name = new DotOperator (location, name, parseIdentifier());
+
+ return parseFunctionCall (new NewOperator (location), name);
+ }
+
+ throwError ("Found " + getTokenName (currentType) + " when expecting an expression");
+ return nullptr;
+ }
+
+ template <typename OpType>
+ Expression* parsePreIncDec()
+ {
+ Expression* e = parseFactor(); // careful - bare pointer is deliberately alised
+ ExpPtr lhs (e), one (new LiteralValue (location, (int) 1));
+ return new SelfAssignment (location, e, new OpType (location, lhs, one));
+ }
+
+ template <typename OpType>
+ Expression* parsePostIncDec (ExpPtr& lhs)
+ {
+ Expression* e = lhs.release(); // careful - bare pointer is deliberately alised
+ ExpPtr lhs2 (e), one (new LiteralValue (location, (int) 1));
+ return new PostAssignment (location, e, new OpType (location, lhs2, one));
+ }
+
+ Expression* parseUnary()
+ {
+ if (matchIf (TokenTypes::minus)) { ExpPtr a (new LiteralValue (location, (int) 0)), b (parseUnary()); return new SubtractionOp (location, a, b); }
+ if (matchIf (TokenTypes::logicalNot)) { ExpPtr a (new LiteralValue (location, (int) 0)), b (parseUnary()); return new EqualsOp (location, a, b); }
+ if (matchIf (TokenTypes::plusplus)) return parsePreIncDec<AdditionOp>();
+ if (matchIf (TokenTypes::minusminus)) return parsePreIncDec<SubtractionOp>();
+
+ return parseFactor();
+ }
+
+ Expression* parseMultiplyDivide()
+ {
+ ExpPtr a (parseUnary());
+
+ for (;;)
+ {
+ if (matchIf (TokenTypes::times)) { ExpPtr b (parseUnary()); a = new MultiplyOp (location, a, b); }
+ else if (matchIf (TokenTypes::divide)) { ExpPtr b (parseUnary()); a = new DivideOp (location, a, b); }
+ else if (matchIf (TokenTypes::modulo)) { ExpPtr b (parseUnary()); a = new ModuloOp (location, a, b); }
+ else break;
+ }
+
+ return a.release();
+ }
+
+ Expression* parseAdditionSubtraction()
+ {
+ ExpPtr a (parseMultiplyDivide());
+
+ for (;;)
+ {
+ if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a = new AdditionOp (location, a, b); }
+ else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a = new SubtractionOp (location, a, b); }
+ else break;
+ }
+
+ return a.release();
+ }
+
+ Expression* parseShiftOperator()
+ {
+ ExpPtr a (parseAdditionSubtraction());
+
+ for (;;)
+ {
+ if (matchIf (TokenTypes::leftShift)) { ExpPtr b (parseExpression()); a = new LeftShiftOp (location, a, b); }
+ else if (matchIf (TokenTypes::rightShift)) { ExpPtr b (parseExpression()); a = new RightShiftOp (location, a, b); }
+ else if (matchIf (TokenTypes::rightShiftUnsigned)) { ExpPtr b (parseExpression()); a = new RightShiftUnsignedOp (location, a, b); }
+ else break;
+ }
+
+ return a.release();
+ }
+
+ Expression* parseComparator()
+ {
+ ExpPtr a (parseShiftOperator());
+
+ for (;;)
+ {
+ if (matchIf (TokenTypes::equals)) { ExpPtr b (parseShiftOperator()); a = new EqualsOp (location, a, b); }
+ else if (matchIf (TokenTypes::notEquals)) { ExpPtr b (parseShiftOperator()); a = new NotEqualsOp (location, a, b); }
+ else if (matchIf (TokenTypes::typeEquals)) { ExpPtr b (parseShiftOperator()); a = new TypeEqualsOp (location, a, b); }
+ else if (matchIf (TokenTypes::typeNotEquals)) { ExpPtr b (parseShiftOperator()); a = new TypeNotEqualsOp (location, a, b); }
+ else if (matchIf (TokenTypes::lessThan)) { ExpPtr b (parseShiftOperator()); a = new LessThanOp (location, a, b); }
+ else if (matchIf (TokenTypes::lessThanOrEqual)) { ExpPtr b (parseShiftOperator()); a = new LessThanOrEqualOp (location, a, b); }
+ else if (matchIf (TokenTypes::greaterThan)) { ExpPtr b (parseShiftOperator()); a = new GreaterThanOp (location, a, b); }
+ else if (matchIf (TokenTypes::greaterThanOrEqual)) { ExpPtr b (parseShiftOperator()); a = new GreaterThanOrEqualOp (location, a, b); }
+ else break;
+ }
+
+ return a.release();
+ }
+
+ Expression* parseLogicOperator()
+ {
+ ExpPtr a (parseComparator());
+
+ for (;;)
+ {
+ if (matchIf (TokenTypes::logicalAnd)) { ExpPtr b (parseComparator()); a = new LogicalAndOp (location, a, b); }
+ else if (matchIf (TokenTypes::logicalOr)) { ExpPtr b (parseComparator()); a = new LogicalOrOp (location, a, b); }
+ else if (matchIf (TokenTypes::bitwiseAnd)) { ExpPtr b (parseComparator()); a = new BitwiseAndOp (location, a, b); }
+ else if (matchIf (TokenTypes::bitwiseOr)) { ExpPtr b (parseComparator()); a = new BitwiseOrOp (location, a, b); }
+ else if (matchIf (TokenTypes::bitwiseXor)) { ExpPtr b (parseComparator()); a = new BitwiseXorOp (location, a, b); }
+ else break;
+ }
+
+ return a.release();
+ }
+
+ Expression* parseTerneryOperator (ExpPtr& condition)
+ {
+ ScopedPointer<ConditionalOp> e (new ConditionalOp (location));
+ e->condition = condition;
+ e->trueBranch = parseExpression();
+ match (TokenTypes::colon);
+ e->falseBranch = parseExpression();
+ return e.release();
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExpressionTreeBuilder)
+ };
+
+ //==============================================================================
+ static var get (Args a, int index) noexcept { return index < a.numArguments ? a.arguments[index] : var(); }
+ static bool isInt (Args a, int index) noexcept { return get (a, index).isInt() || get (a, index).isInt64(); }
+ static int getInt (Args a, int index) noexcept { return get (a, index); }
+ static double getDouble (Args a, int index) noexcept { return get (a, index); }
+ static String getString (Args a, int index) noexcept { return get (a, index).toString(); }
+
+ //==============================================================================
+ struct ObjectClass : public DynamicObject
+ {
+ ObjectClass()
+ {
+ setMethod ("dump", dump);
+ setMethod ("clone", clone);
+ }
+
+ static Identifier getClassName() { static const Identifier i ("Object"); return i; }
+ static var dump (Args a) { DBG (JSON::toString (a.thisObject)); (void) a; return var::undefined(); }
+ static var clone (Args a) { return a.thisObject.clone(); }
+ };
+
+ //==============================================================================
+ struct ArrayClass : public DynamicObject
+ {
+ ArrayClass()
+ {
+ setMethod ("contains", contains);
+ setMethod ("remove", remove);
+ setMethod ("join", join);
+ }
+
+ static Identifier getClassName() { static const Identifier i ("Array"); return i; }
+
+ static var contains (Args a)
+ {
+ if (const Array<var>* array = a.thisObject.getArray())
+ return array->contains (get (a, 0));
+
+ return false;
+ }
+
+ static var remove (Args a)
+ {
+ if (Array<var>* array = a.thisObject.getArray())
+ array->removeAllInstancesOf (get (a, 0));
+
+ return var::undefined();
+ }
+
+ static var join (Args a)
+ {
+ StringArray strings;
+
+ if (const Array<var>* array = a.thisObject.getArray())
+ for (int i = 0; i < array->size(); ++i)
+ strings.add (array->getReference(i).toString());
+
+ return strings.joinIntoString (getString (a, 0));
+ }
+ };
+
+ //==============================================================================
+ struct StringClass : public DynamicObject
+ {
+ StringClass()
+ {
+ setMethod ("substring", substring);
+ setMethod ("indexOf", indexOf);
+ setMethod ("charAt", charAt);
+ setMethod ("charCodeAt", charCodeAt);
+ setMethod ("fromCharCode", fromCharCode);
+ setMethod ("split", split);
+ }
+
+ static Identifier getClassName() { static const Identifier i ("String"); return i; }
+
+ static var fromCharCode (Args a) { return String::charToString (getInt (a, 0)); }
+ static var substring (Args a) { return a.thisObject.toString().substring (getInt (a, 0), getInt (a, 1)); }
+ static var indexOf (Args a) { return a.thisObject.toString().indexOf (getString (a, 0)); }
+ static var charCodeAt (Args a) { return (int) a.thisObject.toString() [getInt (a, 0)]; }
+ static var charAt (Args a) { int p = getInt (a, 0); return a.thisObject.toString().substring (p, p + 1); }
+
+ static var split (Args a)
+ {
+ const String str (a.thisObject.toString());
+ const String sep (getString (a, 0));
+ StringArray strings;
+
+ if (sep.isNotEmpty())
+ strings.addTokens (str, sep.substring (0, 1), "");
+ else // special-case for empty separator: split all chars separately
+ for (String::CharPointerType pos = str.getCharPointer(); ! pos.isEmpty(); ++pos)
+ strings.add (String::charToString (*pos));
+
+ var array;
+ for (int i = 0; i < strings.size(); ++i)
+ array.append (strings[i]);
+
+ return array;
+ }
+ };
+
+ //==============================================================================
+ struct MathClass : public DynamicObject
+ {
+ MathClass()
+ {
+ setMethod ("abs", Math_abs); setMethod ("round", Math_round);
+ setMethod ("random", Math_random); setMethod ("randInt", Math_randInt);
+ setMethod ("min", Math_min); setMethod ("max", Math_max);
+ setMethod ("range", Math_range); setMethod ("sign", Math_sign);
+ setMethod ("PI", Math_pi); setMethod ("E", Math_e);
+ setMethod ("toDegrees", Math_toDegrees); setMethod ("toRadians", Math_toRadians);
+ setMethod ("sin", Math_sin); setMethod ("asin", Math_asin);
+ setMethod ("sinh", Math_sinh); setMethod ("asinh", Math_asinh);
+ setMethod ("cos", Math_cos); setMethod ("acos", Math_acos);
+ setMethod ("cosh", Math_cosh); setMethod ("acosh", Math_acosh);
+ setMethod ("tan", Math_tan); setMethod ("atan", Math_atan);
+ setMethod ("tanh", Math_tanh); setMethod ("atanh", Math_atanh);
+ setMethod ("log", Math_log); setMethod ("log10", Math_log10);
+ setMethod ("exp", Math_exp); setMethod ("pow", Math_pow);
+ setMethod ("sqr", Math_sqr); setMethod ("sqrt", Math_sqrt);
+ }
+
+ static var Math_pi (Args) { return double_Pi; }
+ static var Math_e (Args) { return exp (1.0); }
+ static var Math_random (Args) { return Random::getSystemRandom().nextDouble(); }
+ static var Math_randInt (Args a) { return Random::getSystemRandom().nextInt (Range<int> (getInt (a, 0), getInt (a, 1))); }
+ static var Math_abs (Args a) { return isInt (a, 0) ? var (std::abs (getInt (a, 0))) : var (std::abs (getDouble (a, 0))); }
+ static var Math_round (Args a) { return isInt (a, 0) ? var (roundToInt (getInt (a, 0))) : var (roundToInt (getDouble (a, 0))); }
+ static var Math_sign (Args a) { return isInt (a, 0) ? var (sign (getInt (a, 0))) : var (sign (getDouble (a, 0))); }
+ static var Math_range (Args a) { return isInt (a, 0) ? var (jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) : var (jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); }
+ static var Math_min (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmin (getInt (a, 0), getInt (a, 1))) : var (jmin (getDouble (a, 0), getDouble (a, 1))); }
+ static var Math_max (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmax (getInt (a, 0), getInt (a, 1))) : var (jmax (getDouble (a, 0), getDouble (a, 1))); }
+ static var Math_toDegrees (Args a) { return (180.0 / double_Pi) * getDouble (a, 0); }
+ static var Math_toRadians (Args a) { return (double_Pi / 180.0) * getDouble (a, 0); }
+ static var Math_sin (Args a) { return sin (getDouble (a, 0)); }
+ static var Math_asin (Args a) { return asin (getDouble (a, 0)); }
+ static var Math_cos (Args a) { return cos (getDouble (a, 0)); }
+ static var Math_acos (Args a) { return acos (getDouble (a, 0)); }
+ static var Math_sinh (Args a) { return sinh (getDouble (a, 0)); }
+ static var Math_asinh (Args a) { return asinh (getDouble (a, 0)); }
+ static var Math_cosh (Args a) { return cosh (getDouble (a, 0)); }
+ static var Math_acosh (Args a) { return acosh (getDouble (a, 0)); }
+ static var Math_tan (Args a) { return tan (getDouble (a, 0)); }
+ static var Math_tanh (Args a) { return tanh (getDouble (a, 0)); }
+ static var Math_atan (Args a) { return atan (getDouble (a, 0)); }
+ static var Math_atanh (Args a) { return atanh (getDouble (a, 0)); }
+ static var Math_log (Args a) { return log (getDouble (a, 0)); }
+ static var Math_log10 (Args a) { return log10 (getDouble (a, 0)); }
+ static var Math_exp (Args a) { return exp (getDouble (a, 0)); }
+ static var Math_pow (Args a) { return pow (getDouble (a, 0), getDouble (a, 1)); }
+ static var Math_sqr (Args a) { double x = getDouble (a, 0); return x * x; }
+ static var Math_sqrt (Args a) { return std::sqrt (getDouble (a, 0)); }
+
+ static Identifier getClassName() { static const Identifier i ("Math"); return i; }
+ template <typename Type> static Type sign (Type n) noexcept { return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
+ };
+
+ //==============================================================================
+ struct JSONClass : public DynamicObject
+ {
+ JSONClass() { setMethod ("stringify", stringify); }
+ static Identifier getClassName() { static const Identifier i ("JSON"); return i; }
+ static var stringify (Args a) { return JSON::toString (get (a, 0)); }
+ };
+
+ //==============================================================================
+ struct IntegerClass : public DynamicObject
+ {
+ IntegerClass() { setMethod ("parseInt", parseInt); }
+ static Identifier getClassName() { static const Identifier i ("Integer"); return i; }
+
+ static var parseInt (Args a)
+ {
+ const String s (getString (a, 0).trim());
+
+ return s[0] == '0' ? (s[1] == 'x' ? s.substring(2).getHexValue64() : getOctalValue (s))
+ : s.getLargeIntValue();
+ }
+ };
+
+ //==============================================================================
+ static var trace (Args a) { Logger::outputDebugString (JSON::toString (a.thisObject)); return var::undefined(); }
+ static var charToInt (Args a) { return (int) (getString (a, 0)[0]); }
+
+ static var exec (Args a)
+ {
+ if (RootObject* root = dynamic_cast<RootObject*> (a.thisObject.getObject()))
+ root->execute (getString (a, 0));
+
+ return var::undefined();
+ }
+
+ static var eval (Args a)
+ {
+ if (RootObject* root = dynamic_cast<RootObject*> (a.thisObject.getObject()))
+ return root->evaluate (getString (a, 0));
+
+ return var::undefined();
+ }
+};
+
+//==============================================================================
+JavascriptEngine::JavascriptEngine() : maximumExecutionTime (15.0), root (new RootObject())
+{
+ registerNativeObject (RootObject::ObjectClass ::getClassName(), new RootObject::ObjectClass());
+ registerNativeObject (RootObject::ArrayClass ::getClassName(), new RootObject::ArrayClass());
+ registerNativeObject (RootObject::StringClass ::getClassName(), new RootObject::StringClass());
+ registerNativeObject (RootObject::MathClass ::getClassName(), new RootObject::MathClass());
+ registerNativeObject (RootObject::JSONClass ::getClassName(), new RootObject::JSONClass());
+ registerNativeObject (RootObject::IntegerClass ::getClassName(), new RootObject::IntegerClass());
+}
+
+JavascriptEngine::~JavascriptEngine() {}
+
+void JavascriptEngine::prepareTimeout() const { root->timeout = Time::getCurrentTime() + maximumExecutionTime; }
+
+void JavascriptEngine::registerNativeObject (Identifier name, DynamicObject* object)
+{
+ root->setProperty (name, object);
+}
+
+Result JavascriptEngine::execute (const String& code)
+{
+ try
+ {
+ prepareTimeout();
+ root->execute (code);
+ }
+ catch (String& error)
+ {
+ return Result::fail (error);
+ }
+
+ return Result::ok();
+}
+
+var JavascriptEngine::evaluate (const String& code, Result* result)
+{
+ try
+ {
+ prepareTimeout();
+ if (result != nullptr) *result = Result::ok();
+ return root->evaluate (code);
+ }
+ catch (String& error)
+ {
+ if (result != nullptr) *result = Result::fail (error);
+ }
+
+ return var::undefined();
+}
+
+var JavascriptEngine::callFunction (Identifier function, const var::NativeFunctionArgs& args, Result* result)
+{
+ var returnVal (var::undefined());
+
+ try
+ {
+ prepareTimeout();
+ if (result != nullptr) *result = Result::ok();
+ RootObject::Scope (nullptr, root, root).findAndInvokeMethod (function, args, returnVal);
+ }
+ catch (String& error)
+ {
+ if (result != nullptr) *result = Result::fail (error);
+ }
+
+ return returnVal;
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.h b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.h
new file mode 100644
index 0000000..42368a4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/javascript/juce_Javascript.h
@@ -0,0 +1,105 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+/**
+ A simple javascript interpreter!
+
+ It's not fully standards-compliant, and won't be as fast as the fancy JIT-compiled
+ engines that you get in browsers, but this is an extremely compact, low-overhead javascript
+ interpreter, which is integrated with the juce var and DynamicObject classes. If you need
+ a few simple bits of scripting in your app, and want to be able to easily let the JS
+ work with native objects defined as DynamicObject subclasses, then this might do the job.
+
+ To use, simply create an instance of this class and call execute() to run your code.
+ Variables that the script sets can be retrieved with evaluate(), and if you need to provide
+ native objects for the script to use, you can add them with registerNativeObject().
+
+ One caveat: Because the values and objects that the engine works with are DynamicObject
+ and var objects, they use reference-counting rather than garbage-collection, so if your
+ script creates complex connections between objects, you run the risk of creating cyclic
+ dependencies and hence leaking.
+*/
+class JavascriptEngine
+{
+public:
+ /** Creates an instance of the engine.
+ This creates a root namespace and defines some basic Object, String, Array
+ and Math library methods.
+ */
+ JavascriptEngine();
+
+ /** Destructor. */
+ ~JavascriptEngine();
+
+ /** Attempts to parse and run a block of javascript code.
+ If there's a parse or execution error, the error description is returned in
+ the result.
+ You can specify a maximum time for which the program is allowed to run, and
+ it'll return with an error message if this time is exceeded.
+ */
+ Result execute (const String& javascriptCode);
+
+ /** Attempts to parse and run a javascript expression, and returns the result.
+ If there's a syntax error, or the expression can't be evaluated, the return value
+ will be var::undefined(). The errorMessage parameter gives you a way to find out
+ any parsing errors.
+ You can specify a maximum time for which the program is allowed to run, and
+ it'll return with an error message if this time is exceeded.
+ */
+ var evaluate (const String& javascriptCode,
+ Result* errorMessage = nullptr);
+
+ /** Calls a function in the root namespace, and returns the result.
+ The function arguments are passed in the same format as used by native
+ methods in the var class.
+ */
+ var callFunction (Identifier function,
+ const var::NativeFunctionArgs& args,
+ Result* errorMessage = nullptr);
+
+ /** Adds a native object to the root namespace.
+ The object passed-in is reference-counted, and will be retained by the
+ engine until the engine is deleted. The name must be a simple JS identifier,
+ without any dots.
+ */
+ void registerNativeObject (Identifier objectName, DynamicObject* object);
+
+ /** This value indicates how long a call to one of the evaluate methods is permitted
+ to run before timing-out and failing.
+ The default value is a number of seconds, but you can change this to whatever value
+ suits your application.
+ */
+ RelativeTime maximumExecutionTime;
+
+private:
+ JUCE_PUBLIC_IN_DLL_BUILD (struct RootObject)
+ ReferenceCountedObjectPtr<RootObject> root;
+ void prepareTimeout() const;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.cpp
new file mode 100644
index 0000000..c6040cb
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.cpp
@@ -0,0 +1,226 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#if defined (JUCE_CORE_H_INCLUDED) && ! JUCE_AMALGAMATED_INCLUDE
+ /* When you add this cpp file to your project, you mustn't include it in a file where you've
+ already included any other headers - just put it inside a file on its own, possibly with your config
+ flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
+ header files that the compiler may be using.
+ */
+ #error "Incorrect use of JUCE cpp file"
+#endif
+
+// Your project must contain an AppConfig.h file with your project-specific settings in it,
+// and your header search path must make it accessible to the module's files.
+#include "htio2/JUCE-3.0.8/AppConfig.h"
+
+//==============================================================================
+#include "native/juce_BasicNativeHeaders.h"
+#include "juce_core.h"
+
+#include <locale>
+#include <cctype>
+#include <sys/timeb.h>
+
+#if ! JUCE_ANDROID
+ #include <cwctype>
+#endif
+
+#if JUCE_WINDOWS
+ #include <ctime>
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+
+ #if ! JUCE_MINGW
+ #include <Dbghelp.h>
+
+ #if ! JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+ #pragma comment (lib, "DbgHelp.lib")
+ #endif
+ #endif
+
+ #if JUCE_MINGW
+ #include <ws2spi.h>
+ #endif
+
+#else
+ #if JUCE_LINUX || JUCE_ANDROID
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/errno.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #endif
+
+ #if JUCE_LINUX
+ #include <langinfo.h>
+ #endif
+
+ #include <pwd.h>
+ #include <fcntl.h>
+ #include <netdb.h>
+ #include <arpa/inet.h>
+ #include <netinet/tcp.h>
+ #include <sys/time.h>
+ #include <net/if.h>
+ #include <sys/ioctl.h>
+
+ #if ! JUCE_ANDROID
+ #include <execinfo.h>
+ #endif
+#endif
+
+#if JUCE_MAC || JUCE_IOS
+ #include <xlocale.h>
+ #include <mach/mach.h>
+#endif
+
+#if JUCE_ANDROID
+ #include <android/log.h>
+#endif
+
+
+//==============================================================================
+namespace htio2
+{
+namespace juce
+{
+
+#include "containers/juce_AbstractFifo.cpp"
+#include "containers/juce_NamedValueSet.cpp"
+#include "containers/juce_PropertySet.cpp"
+#include "containers/juce_Variant.cpp"
+#include "files/juce_DirectoryIterator.cpp"
+#include "files/juce_File.cpp"
+#include "files/juce_FileInputStream.cpp"
+#include "files/juce_FileOutputStream.cpp"
+#include "files/juce_FileSearchPath.cpp"
+#include "files/juce_TemporaryFile.cpp"
+#include "javascript/juce_JSON.cpp"
+#include "javascript/juce_Javascript.cpp"
+#include "containers/juce_DynamicObject.cpp"
+#include "logging/juce_FileLogger.cpp"
+#include "logging/juce_Logger.cpp"
+#include "maths/juce_BigInteger.cpp"
+#include "maths/juce_Expression.cpp"
+#include "maths/juce_Random.cpp"
+#include "memory/juce_MemoryBlock.cpp"
+#include "misc/juce_Result.cpp"
+#include "misc/juce_Uuid.cpp"
+#include "network/juce_MACAddress.cpp"
+#include "network/juce_NamedPipe.cpp"
+#include "network/juce_Socket.cpp"
+#include "network/juce_IPAddress.cpp"
+#include "streams/juce_BufferedInputStream.cpp"
+#include "streams/juce_FileInputSource.cpp"
+#include "streams/juce_InputStream.cpp"
+#include "streams/juce_MemoryInputStream.cpp"
+#include "streams/juce_MemoryOutputStream.cpp"
+#include "streams/juce_SubregionStream.cpp"
+#include "system/juce_SystemStats.cpp"
+#include "text/juce_CharacterFunctions.cpp"
+#include "text/juce_Identifier.cpp"
+#include "text/juce_LocalisedStrings.cpp"
+#include "text/juce_String.cpp"
+#include "streams/juce_OutputStream.cpp"
+#include "text/juce_StringArray.cpp"
+#include "text/juce_StringPairArray.cpp"
+#include "text/juce_StringPool.cpp"
+#include "text/juce_TextDiff.cpp"
+#include "threads/juce_ReadWriteLock.cpp"
+#include "threads/juce_Thread.cpp"
+#include "threads/juce_ThreadPool.cpp"
+#include "threads/juce_TimeSliceThread.cpp"
+#include "time/juce_PerformanceCounter.cpp"
+#include "time/juce_RelativeTime.cpp"
+#include "time/juce_Time.cpp"
+#include "unit_tests/juce_UnitTest.cpp"
+#include "xml/juce_XmlDocument.cpp"
+#include "xml/juce_XmlElement.cpp"
+#include "zip/juce_GZIPDecompressorInputStream.cpp"
+#include "zip/juce_GZIPCompressorOutputStream.cpp"
+#include "zip/juce_ZipFile.cpp"
+#include "files/juce_FileFilter.cpp"
+#include "files/juce_WildcardFileFilter.cpp"
+
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS
+#include "native/juce_osx_ObjCHelpers.h"
+#endif
+
+#if JUCE_ANDROID
+#include "native/juce_android_JNIHelpers.h"
+#endif
+
+#if ! JUCE_WINDOWS
+#include "native/juce_posix_SharedCode.h"
+#include "native/juce_posix_NamedPipe.cpp"
+#endif
+
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS
+#include "native/juce_mac_Files.mm"
+#include "native/juce_mac_Network.mm"
+#include "native/juce_mac_Strings.mm"
+#include "native/juce_mac_SystemStats.mm"
+#include "native/juce_mac_Threads.mm"
+
+//==============================================================================
+#elif JUCE_WINDOWS
+#include "native/juce_win32_ComSmartPtr.h"
+#include "native/juce_win32_Files.cpp"
+#include "native/juce_win32_Network.cpp"
+#include "native/juce_win32_Registry.cpp"
+#include "native/juce_win32_SystemStats.cpp"
+#include "native/juce_win32_Threads.cpp"
+
+//==============================================================================
+#elif JUCE_LINUX
+#include "native/juce_linux_CommonFile.cpp"
+#include "native/juce_linux_Files.cpp"
+#include "native/juce_linux_Network.cpp"
+#include "native/juce_linux_SystemStats.cpp"
+#include "native/juce_linux_Threads.cpp"
+
+//==============================================================================
+#elif JUCE_ANDROID
+#include "native/juce_linux_CommonFile.cpp"
+#include "native/juce_android_Files.cpp"
+#include "native/juce_android_Misc.cpp"
+#include "native/juce_android_Network.cpp"
+#include "native/juce_android_SystemStats.cpp"
+#include "native/juce_android_Threads.cpp"
+
+#endif
+
+#include "threads/juce_ChildProcess.cpp"
+#include "threads/juce_HighResolutionTimer.cpp"
+#include "network/juce_URL.cpp"
+
+} // namespace juce
+} // namespace htio2
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.h b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.h
new file mode 100644
index 0000000..7e0bfe2
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.h
@@ -0,0 +1,286 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CORE_H_INCLUDED
+#define JUCE_CORE_H_INCLUDED
+
+#ifndef JUCE_MODULE_AVAILABLE_juce_core
+ /* If you fail to make sure that all your compile units are building JUCE with the same set of
+ option flags, then there's a risk that different compile units will treat the classes as having
+ different memory layouts, leading to very nasty memory corruption errors when they all get
+ linked together. That's why it's best to always include the Introjucer-generated AppConfig.h
+ file before any juce headers.
+
+ Note that if you do have an AppConfig.h file and hit this warning, it means that it doesn't
+ contain the JUCE_MODULE_AVAILABLE_xxx flags, which are necessary for some inter-module
+ functionality to work correctly. In that case, you should either rebuild your AppConfig.h with
+ the latest introjucer, or fix it manually to contain these flags.
+ */
+ #ifdef _MSC_VER
+ #pragma message ("Have you included your AppConfig.h file before including the JUCE headers?")
+ #else
+ #warning "Have you included your AppConfig.h file before including the JUCE headers?"
+ #endif
+#endif
+
+//==============================================================================
+#include "system/juce_TargetPlatform.h"
+
+//=============================================================================
+/** Config: JUCE_FORCE_DEBUG
+
+ Normally, JUCE_DEBUG is set to 1 or 0 based on compiler and project settings,
+ but if you define this value, you can override this to force it to be true or false.
+*/
+#ifndef JUCE_FORCE_DEBUG
+ //#define JUCE_FORCE_DEBUG 0
+#endif
+
+//=============================================================================
+/** Config: JUCE_LOG_ASSERTIONS
+
+ If this flag is enabled, the jassert and jassertfalse macros will always use Logger::writeToLog()
+ to write a message when an assertion happens.
+
+ Enabling it will also leave this turned on in release builds. When it's disabled,
+ however, the jassert and jassertfalse macros will not be compiled in a
+ release build.
+
+ @see jassert, jassertfalse, Logger
+*/
+#ifndef JUCE_LOG_ASSERTIONS
+ #if JUCE_ANDROID
+ #define JUCE_LOG_ASSERTIONS 1
+ #else
+ #define JUCE_LOG_ASSERTIONS 0
+ #endif
+#endif
+
+//=============================================================================
+/** Config: JUCE_CHECK_MEMORY_LEAKS
+
+ Enables a memory-leak check for certain objects when the app terminates. See the LeakedObjectDetector
+ class and the JUCE_LEAK_DETECTOR macro for more details about enabling leak checking for specific classes.
+*/
+#if JUCE_DEBUG && ! defined (JUCE_CHECK_MEMORY_LEAKS)
+ #define JUCE_CHECK_MEMORY_LEAKS 1
+#endif
+
+//=============================================================================
+/** Config: JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+
+ In a Visual C++ build, this can be used to stop the required system libs being
+ automatically added to the link stage.
+*/
+#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+ #define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 0
+#endif
+
+/** Config: JUCE_INCLUDE_ZLIB_CODE
+ This can be used to disable Juce's embedded 3rd-party zlib code.
+ You might need to tweak this if you're linking to an external zlib library in your app,
+ but for normal apps, this option should be left alone.
+
+ If you disable this, you might also want to set a value for JUCE_ZLIB_INCLUDE_PATH, to
+ specify the path where your zlib headers live.
+*/
+#ifndef JUCE_INCLUDE_ZLIB_CODE
+ #define JUCE_INCLUDE_ZLIB_CODE 1
+#endif
+
+#ifndef JUCE_ZLIB_INCLUDE_PATH
+ #define JUCE_ZLIB_INCLUDE_PATH <zlib.h>
+#endif
+
+/* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS
+ If enabled, this will add some exception-catching code to forward unhandled exceptions
+ to your JUCEApplicationBase::unhandledException() callback.
+*/
+#ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS
+ //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1
+#endif
+
+#ifndef JUCE_STRING_UTF_TYPE
+ #define JUCE_STRING_UTF_TYPE 8
+#endif
+
+//=============================================================================
+//=============================================================================
+#if JUCE_MSVC
+ #pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state)
+ #pragma warning (push)
+ #pragma warning (disable: 4786) // (long class name warning)
+ #ifdef __INTEL_COMPILER
+ #pragma warning (disable: 1125)
+ #endif
+#endif
+
+#include "system/juce_StandardHeader.h"
+
+namespace htio2
+{
+namespace juce
+{
+
+class StringRef;
+class MemoryBlock;
+class File;
+class InputStream;
+class OutputStream;
+class DynamicObject;
+class FileInputStream;
+class FileOutputStream;
+class XmlElement;
+class JSONFormatter;
+
+extern JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger();
+extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noexcept;
+
+#include "memory/juce_Memory.h"
+#include "maths/juce_MathsFunctions.h"
+#include "memory/juce_ByteOrder.h"
+#include "memory/juce_Atomic.h"
+#include "text/juce_CharacterFunctions.h"
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4514 4996)
+#endif
+
+#include "text/juce_CharPointer_UTF8.h"
+#include "text/juce_CharPointer_UTF16.h"
+#include "text/juce_CharPointer_UTF32.h"
+#include "text/juce_CharPointer_ASCII.h"
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+#include "text/juce_String.h"
+#include "text/juce_StringRef.h"
+#include "logging/juce_Logger.h"
+#include "memory/juce_LeakedObjectDetector.h"
+#include "memory/juce_ContainerDeletePolicy.h"
+#include "memory/juce_HeapBlock.h"
+#include "memory/juce_MemoryBlock.h"
+#include "memory/juce_ReferenceCountedObject.h"
+#include "memory/juce_ScopedPointer.h"
+#include "memory/juce_OptionalScopedPointer.h"
+#include "memory/juce_Singleton.h"
+#include "memory/juce_WeakReference.h"
+#include "threads/juce_ScopedLock.h"
+#include "threads/juce_CriticalSection.h"
+#include "maths/juce_Range.h"
+#include "containers/juce_ElementComparator.h"
+#include "containers/juce_ArrayAllocationBase.h"
+#include "containers/juce_Array.h"
+#include "containers/juce_LinkedListPointer.h"
+#include "containers/juce_OwnedArray.h"
+#include "containers/juce_ReferenceCountedArray.h"
+#include "containers/juce_ScopedValueSetter.h"
+#include "containers/juce_SortedSet.h"
+#include "containers/juce_SparseSet.h"
+#include "containers/juce_AbstractFifo.h"
+#include "text/juce_NewLine.h"
+#include "text/juce_StringPool.h"
+#include "text/juce_Identifier.h"
+#include "text/juce_StringArray.h"
+#include "text/juce_StringPairArray.h"
+#include "text/juce_TextDiff.h"
+#include "text/juce_LocalisedStrings.h"
+#include "misc/juce_Result.h"
+#include "containers/juce_Variant.h"
+#include "containers/juce_NamedValueSet.h"
+#include "containers/juce_DynamicObject.h"
+#include "containers/juce_HashMap.h"
+#include "time/juce_RelativeTime.h"
+#include "time/juce_Time.h"
+#include "streams/juce_InputStream.h"
+#include "streams/juce_OutputStream.h"
+#include "streams/juce_BufferedInputStream.h"
+#include "streams/juce_MemoryInputStream.h"
+#include "streams/juce_MemoryOutputStream.h"
+#include "streams/juce_SubregionStream.h"
+#include "streams/juce_InputSource.h"
+#include "files/juce_File.h"
+#include "files/juce_DirectoryIterator.h"
+#include "files/juce_FileInputStream.h"
+#include "files/juce_FileOutputStream.h"
+#include "files/juce_FileSearchPath.h"
+#include "files/juce_MemoryMappedFile.h"
+#include "files/juce_TemporaryFile.h"
+#include "files/juce_FileFilter.h"
+#include "files/juce_WildcardFileFilter.h"
+#include "streams/juce_FileInputSource.h"
+#include "logging/juce_FileLogger.h"
+#include "javascript/juce_JSON.h"
+#include "javascript/juce_Javascript.h"
+#include "maths/juce_BigInteger.h"
+#include "maths/juce_Expression.h"
+#include "maths/juce_Random.h"
+#include "misc/juce_Uuid.h"
+#include "misc/juce_WindowsRegistry.h"
+#include "system/juce_PlatformDefs.h"
+#include "system/juce_SystemStats.h"
+#include "threads/juce_ChildProcess.h"
+#include "threads/juce_DynamicLibrary.h"
+#include "threads/juce_HighResolutionTimer.h"
+#include "threads/juce_InterProcessLock.h"
+#include "threads/juce_Process.h"
+#include "threads/juce_SpinLock.h"
+#include "threads/juce_WaitableEvent.h"
+#include "threads/juce_Thread.h"
+#include "threads/juce_ThreadLocalValue.h"
+#include "threads/juce_ThreadPool.h"
+#include "threads/juce_TimeSliceThread.h"
+#include "threads/juce_ReadWriteLock.h"
+#include "threads/juce_ScopedReadLock.h"
+#include "threads/juce_ScopedWriteLock.h"
+#include "network/juce_IPAddress.h"
+#include "network/juce_MACAddress.h"
+#include "network/juce_NamedPipe.h"
+#include "network/juce_Socket.h"
+#include "network/juce_URL.h"
+#include "time/juce_PerformanceCounter.h"
+#include "unit_tests/juce_UnitTest.h"
+#include "xml/juce_XmlDocument.h"
+#include "xml/juce_XmlElement.h"
+#include "zip/juce_GZIPCompressorOutputStream.h"
+#include "zip/juce_GZIPDecompressorInputStream.h"
+#include "zip/juce_ZipFile.h"
+#include "containers/juce_PropertySet.h"
+#include "memory/juce_SharedResourcePointer.h"
+
+} // namespace juce
+} // namespace htio2
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // JUCE_CORE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.mm
new file mode 100644
index 0000000..90a2f7c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_core.mm
@@ -0,0 +1,29 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#include "juce_core.cpp"
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/juce_module_info b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_module_info
new file mode 100644
index 0000000..7fb2073
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/juce_module_info
@@ -0,0 +1,38 @@
+{
+ "id": "juce_core",
+ "name": "JUCE core classes",
+ "version": "3.0.8",
+ "description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.",
+ "website": "http://www.juce.com/juce",
+ "license": "ISC Permissive",
+
+ "dependencies": [],
+
+ "include": "juce_core.h",
+
+ "compile": [ { "file": "juce_core.cpp", "target": "! xcode" },
+ { "file": "juce_core.mm", "target": "xcode" } ],
+
+ "browse": [ "text/*",
+ "maths/*",
+ "memory/*",
+ "containers/*",
+ "threads/*",
+ "time/*",
+ "files/*",
+ "network/*",
+ "streams/*",
+ "logging/*",
+ "system/*",
+ "xml/*",
+ "javascript/*",
+ "zip/*",
+ "unit_tests/*",
+ "misc/*",
+ "native/*" ],
+
+ "OSXFrameworks": "Cocoa IOKit",
+ "iOSFrameworks": "Foundation",
+ "LinuxLibs": "rt dl pthread",
+ "mingwLibs": "uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi rpcrt4 winmm"
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.cpp
new file mode 100644
index 0000000..8cadfda
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.cpp
@@ -0,0 +1,134 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+FileLogger::FileLogger (const File& file,
+ const String& welcomeMessage,
+ const int64 maxInitialFileSizeBytes)
+ : logFile (file)
+{
+ if (maxInitialFileSizeBytes >= 0)
+ trimFileSize (maxInitialFileSizeBytes);
+
+ if (! file.exists())
+ file.create(); // (to create the parent directories)
+
+ String welcome;
+ welcome << newLine
+ << "**********************************************************" << newLine
+ << welcomeMessage << newLine
+ << "Log started: " << Time::getCurrentTime().toString (true, true) << newLine;
+
+ FileLogger::logMessage (welcome);
+}
+
+FileLogger::~FileLogger() {}
+
+//==============================================================================
+void FileLogger::logMessage (const String& message)
+{
+ const ScopedLock sl (logLock);
+ DBG (message);
+ FileOutputStream out (logFile, 256);
+ out << message << newLine;
+}
+
+void FileLogger::trimFileSize (int64 maxFileSizeBytes) const
+{
+ if (maxFileSizeBytes <= 0)
+ {
+ logFile.deleteFile();
+ }
+ else
+ {
+ const int64 fileSize = logFile.getSize();
+
+ if (fileSize > maxFileSizeBytes)
+ {
+ TemporaryFile tempFile (logFile);
+
+ {
+ FileOutputStream out (tempFile.getFile());
+ FileInputStream in (logFile);
+
+ if (! (out.openedOk() && in.openedOk()))
+ return;
+
+ in.setPosition (fileSize - maxFileSizeBytes);
+
+ for (;;)
+ {
+ const char c = in.readByte();
+ if (c == 0)
+ return;
+
+ if (c == '\n' || c == '\r')
+ {
+ out << c;
+ break;
+ }
+ }
+
+ out.writeFromInputStream (in, -1);
+ }
+
+ tempFile.overwriteTargetFileWithTemporary();
+ }
+ }
+}
+
+//==============================================================================
+File FileLogger::getSystemLogFileFolder()
+{
+ #if JUCE_MAC
+ return File ("~/Library/Logs");
+ #else
+ return File::getSpecialLocation (File::userApplicationDataDirectory);
+ #endif
+}
+
+FileLogger* FileLogger::createDefaultAppLogger (const String& logFileSubDirectoryName,
+ const String& logFileName,
+ const String& welcomeMessage,
+ const int64 maxInitialFileSizeBytes)
+{
+ return new FileLogger (getSystemLogFileFolder().getChildFile (logFileSubDirectoryName)
+ .getChildFile (logFileName),
+ welcomeMessage, maxInitialFileSizeBytes);
+}
+
+FileLogger* FileLogger::createDateStampedLogger (const String& logFileSubDirectoryName,
+ const String& logFileNameRoot,
+ const String& logFileNameSuffix,
+ const String& welcomeMessage)
+{
+ return new FileLogger (getSystemLogFileFolder().getChildFile (logFileSubDirectoryName)
+ .getChildFile (logFileNameRoot + Time::getCurrentTime().formatted ("%Y-%m-%d_%H-%M-%S"))
+ .withFileExtension (logFileNameSuffix)
+ .getNonexistentSibling(),
+ welcomeMessage, 0);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.h b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.h
new file mode 100644
index 0000000..6be1668
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_FileLogger.h
@@ -0,0 +1,135 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILELOGGER_H_INCLUDED
+#define JUCE_FILELOGGER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A simple implementation of a Logger that writes to a file.
+
+ @see Logger
+*/
+class JUCE_API FileLogger : public Logger
+{
+public:
+ //==============================================================================
+ /** Creates a FileLogger for a given file.
+
+ @param fileToWriteTo the file that to use - new messages will be appended
+ to the file. If the file doesn't exist, it will be created,
+ along with any parent directories that are needed.
+ @param welcomeMessage when opened, the logger will write a header to the log, along
+ with the current date and time, and this welcome message
+ @param maxInitialFileSizeBytes if this is zero or greater, then if the file already exists
+ but is larger than this number of bytes, then the start of the
+ file will be truncated to keep the size down. This prevents a log
+ file getting ridiculously large over time. The file will be truncated
+ at a new-line boundary. If this value is less than zero, no size limit
+ will be imposed; if it's zero, the file will always be deleted. Note that
+ the size is only checked once when this object is created - any logging
+ that is done later will be appended without any checking
+ */
+ FileLogger (const File& fileToWriteTo,
+ const String& welcomeMessage,
+ const int64 maxInitialFileSizeBytes = 128 * 1024);
+
+ /** Destructor. */
+ ~FileLogger();
+
+ //==============================================================================
+ /** Returns the file that this logger is writing to. */
+ const File& getLogFile() const noexcept { return logFile; }
+
+ //==============================================================================
+ /** Helper function to create a log file in the correct place for this platform.
+
+ The method might return nullptr if the file can't be created for some reason.
+
+ @param logFileSubDirectoryName the name of the subdirectory to create inside the logs folder (as
+ returned by getSystemLogFileFolder). It's best to use something
+ like the name of your application here.
+ @param logFileName the name of the file to create, e.g. "MyAppLog.txt".
+ @param welcomeMessage a message that will be written to the log when it's opened.
+ @param maxInitialFileSizeBytes (see the FileLogger constructor for more info on this)
+ */
+ static FileLogger* createDefaultAppLogger (const String& logFileSubDirectoryName,
+ const String& logFileName,
+ const String& welcomeMessage,
+ const int64 maxInitialFileSizeBytes = 128 * 1024);
+
+ /** Helper function to create a log file in the correct place for this platform.
+
+ The filename used is based on the root and suffix strings provided, along with a
+ time and date string, meaning that a new, empty log file will be always be created
+ rather than appending to an exising one.
+
+ The method might return nullptr if the file can't be created for some reason.
+
+ @param logFileSubDirectoryName the name of the subdirectory to create inside the logs folder (as
+ returned by getSystemLogFileFolder). It's best to use something
+ like the name of your application here.
+ @param logFileNameRoot the start of the filename to use, e.g. "MyAppLog_". This will have
+ a timestamp and the logFileNameSuffix appended to it
+ @param logFileNameSuffix the file suffix to use, e.g. ".txt"
+ @param welcomeMessage a message that will be written to the log when it's opened.
+ */
+ static FileLogger* createDateStampedLogger (const String& logFileSubDirectoryName,
+ const String& logFileNameRoot,
+ const String& logFileNameSuffix,
+ const String& welcomeMessage);
+
+ //==============================================================================
+ /** Returns an OS-specific folder where log-files should be stored.
+
+ On Windows this will return a logger with a path such as:
+ c:\\Documents and Settings\\username\\Application Data\\[logFileSubDirectoryName]\\[logFileName]
+
+ On the Mac it'll create something like:
+ ~/Library/Logs/[logFileSubDirectoryName]/[logFileName]
+
+ @see createDefaultAppLogger
+ */
+ static File getSystemLogFileFolder();
+
+ // (implementation of the Logger virtual method)
+ void logMessage (const String&);
+
+private:
+ //==============================================================================
+ File logFile;
+ CriticalSection logLock;
+
+ void trimFileSize (int64 maxFileSizeBytes) const;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileLogger)
+};
+
+
+#endif // JUCE_FILELOGGER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.cpp
new file mode 100644
index 0000000..0b1c8d6
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.cpp
@@ -0,0 +1,63 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Logger::Logger() {}
+
+Logger::~Logger()
+{
+ // You're deleting this logger while it's still being used!
+ // Always call Logger::setCurrentLogger (nullptr) before deleting the active logger.
+ jassert (currentLogger != this);
+}
+
+Logger* Logger::currentLogger = nullptr;
+
+void Logger::setCurrentLogger (Logger* const newLogger) noexcept { currentLogger = newLogger; }
+Logger* Logger::getCurrentLogger() noexcept { return currentLogger; }
+
+void Logger::writeToLog (const String& message)
+{
+ if (currentLogger != nullptr)
+ currentLogger->logMessage (message);
+ else
+ outputDebugString (message);
+}
+
+#if JUCE_LOG_ASSERTIONS || JUCE_DEBUG
+void JUCE_API JUCE_CALLTYPE logAssertion (const char* const filename, const int lineNum) noexcept
+{
+ String m ("JUCE Assertion failure in ");
+ m << File::createFileWithoutCheckingPath (filename).getFileName() << ':' << lineNum;
+
+ #if JUCE_LOG_ASSERTIONS
+ Logger::writeToLog (m);
+ #else
+ DBG (m);
+ #endif
+}
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.h b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.h
new file mode 100644
index 0000000..d0d3af5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/logging/juce_Logger.h
@@ -0,0 +1,97 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_LOGGER_H_INCLUDED
+#define JUCE_LOGGER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Acts as an application-wide logging class.
+
+ A subclass of Logger can be created and passed into the Logger::setCurrentLogger
+ method and this will then be used by all calls to writeToLog.
+
+ The logger class also contains methods for writing messages to the debugger's
+ output stream.
+
+ @see FileLogger
+*/
+class JUCE_API Logger
+{
+public:
+ //==============================================================================
+ /** Destructor. */
+ virtual ~Logger();
+
+ //==============================================================================
+ /** Sets the current logging class to use.
+
+ Note that the object passed in will not be owned or deleted by the logger, so
+ the caller must make sure that it is not deleted while still being used.
+ A null pointer can be passed-in to disable any logging.
+ */
+ static void JUCE_CALLTYPE setCurrentLogger (Logger* newLogger) noexcept;
+
+ /** Returns the current logger, or nullptr if none has been set. */
+ static Logger* getCurrentLogger() noexcept;
+
+ /** Writes a string to the current logger.
+
+ This will pass the string to the logger's logMessage() method if a logger
+ has been set.
+
+ @see logMessage
+ */
+ static void JUCE_CALLTYPE writeToLog (const String& message);
+
+
+ //==============================================================================
+ /** Writes a message to the standard error stream.
+
+ This can be called directly, or by using the DBG() macro in
+ juce_PlatformDefs.h (which will avoid calling the method in non-debug builds).
+ */
+ static void JUCE_CALLTYPE outputDebugString (const String& text);
+
+
+protected:
+ //==============================================================================
+ Logger();
+
+ /** This is overloaded by subclasses to implement custom logging behaviour.
+ @see setCurrentLogger
+ */
+ virtual void logMessage (const String& message) = 0;
+
+private:
+ static Logger* currentLogger;
+};
+
+
+#endif // JUCE_LOGGER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.cpp
new file mode 100644
index 0000000..b1c42b6
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.cpp
@@ -0,0 +1,1014 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+namespace
+{
+ inline size_t bitToIndex (const int bit) noexcept { return (size_t) (bit >> 5); }
+ inline uint32 bitToMask (const int bit) noexcept { return (uint32) 1 << (bit & 31); }
+}
+
+//==============================================================================
+BigInteger::BigInteger()
+ : numValues (4),
+ highestBit (-1),
+ negative (false)
+{
+ values.calloc (numValues + 1);
+}
+
+BigInteger::BigInteger (const int32 value)
+ : numValues (4),
+ highestBit (31),
+ negative (value < 0)
+{
+ values.calloc (numValues + 1);
+ values[0] = (uint32) abs (value);
+ highestBit = getHighestBit();
+}
+
+BigInteger::BigInteger (const uint32 value)
+ : numValues (4),
+ highestBit (31),
+ negative (false)
+{
+ values.calloc (numValues + 1);
+ values[0] = value;
+ highestBit = getHighestBit();
+}
+
+BigInteger::BigInteger (int64 value)
+ : numValues (4),
+ highestBit (63),
+ negative (value < 0)
+{
+ values.calloc (numValues + 1);
+
+ if (value < 0)
+ value = -value;
+
+ values[0] = (uint32) value;
+ values[1] = (uint32) (value >> 32);
+ highestBit = getHighestBit();
+}
+
+BigInteger::BigInteger (const BigInteger& other)
+ : numValues ((size_t) jmax ((size_t) 4, bitToIndex (other.highestBit) + 1)),
+ highestBit (other.getHighestBit()),
+ negative (other.negative)
+{
+ values.malloc (numValues + 1);
+ memcpy (values, other.values, sizeof (uint32) * (numValues + 1));
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+BigInteger::BigInteger (BigInteger&& other) noexcept
+ : values (static_cast <HeapBlock <uint32>&&> (other.values)),
+ numValues (other.numValues),
+ highestBit (other.highestBit),
+ negative (other.negative)
+{
+}
+
+BigInteger& BigInteger::operator= (BigInteger&& other) noexcept
+{
+ values = static_cast <HeapBlock <uint32>&&> (other.values);
+ numValues = other.numValues;
+ highestBit = other.highestBit;
+ negative = other.negative;
+ return *this;
+}
+#endif
+
+BigInteger::~BigInteger()
+{
+}
+
+void BigInteger::swapWith (BigInteger& other) noexcept
+{
+ values.swapWith (other.values);
+ std::swap (numValues, other.numValues);
+ std::swap (highestBit, other.highestBit);
+ std::swap (negative, other.negative);
+}
+
+BigInteger& BigInteger::operator= (const BigInteger& other)
+{
+ if (this != &other)
+ {
+ highestBit = other.getHighestBit();
+ jassert (other.numValues >= 4);
+ numValues = (size_t) jmax ((size_t) 4, bitToIndex (highestBit) + 1);
+ negative = other.negative;
+ values.malloc (numValues + 1);
+ memcpy (values, other.values, sizeof (uint32) * (numValues + 1));
+ }
+
+ return *this;
+}
+
+void BigInteger::ensureSize (const size_t numVals)
+{
+ if (numVals + 2 >= numValues)
+ {
+ size_t oldSize = numValues;
+ numValues = ((numVals + 2) * 3) / 2;
+ values.realloc (numValues + 1);
+
+ while (oldSize < numValues)
+ values [oldSize++] = 0;
+ }
+}
+
+//==============================================================================
+bool BigInteger::operator[] (const int bit) const noexcept
+{
+ return bit <= highestBit && bit >= 0
+ && ((values [bitToIndex (bit)] & bitToMask (bit)) != 0);
+}
+
+int BigInteger::toInteger() const noexcept
+{
+ const int n = (int) (values[0] & 0x7fffffff);
+ return negative ? -n : n;
+}
+
+int64 BigInteger::toInt64() const noexcept
+{
+ const int64 n = (((int64) (values[1] & 0x7fffffff)) << 32) | values[0];
+ return negative ? -n : n;
+}
+
+BigInteger BigInteger::getBitRange (int startBit, int numBits) const
+{
+ BigInteger r;
+ numBits = jmin (numBits, getHighestBit() + 1 - startBit);
+ r.ensureSize ((size_t) bitToIndex (numBits));
+ r.highestBit = numBits;
+
+ int i = 0;
+ while (numBits > 0)
+ {
+ r.values[i++] = getBitRangeAsInt (startBit, (int) jmin (32, numBits));
+ numBits -= 32;
+ startBit += 32;
+ }
+
+ r.highestBit = r.getHighestBit();
+ return r;
+}
+
+uint32 BigInteger::getBitRangeAsInt (const int startBit, int numBits) const noexcept
+{
+ if (numBits > 32)
+ {
+ jassertfalse; // use getBitRange() if you need more than 32 bits..
+ numBits = 32;
+ }
+
+ numBits = jmin (numBits, highestBit + 1 - startBit);
+
+ if (numBits <= 0)
+ return 0;
+
+ const size_t pos = bitToIndex (startBit);
+ const int offset = startBit & 31;
+ const int endSpace = 32 - numBits;
+
+ uint32 n = ((uint32) values [pos]) >> offset;
+
+ if (offset > endSpace)
+ n |= ((uint32) values [pos + 1]) << (32 - offset);
+
+ return n & (((uint32) 0xffffffff) >> endSpace);
+}
+
+void BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet)
+{
+ if (numBits > 32)
+ {
+ jassertfalse;
+ numBits = 32;
+ }
+
+ for (int i = 0; i < numBits; ++i)
+ {
+ setBit (startBit + i, (valueToSet & 1) != 0);
+ valueToSet >>= 1;
+ }
+}
+
+//==============================================================================
+void BigInteger::clear()
+{
+ if (numValues > 16)
+ {
+ numValues = 4;
+ values.calloc (numValues + 1);
+ }
+ else
+ {
+ values.clear (numValues + 1);
+ }
+
+ highestBit = -1;
+ negative = false;
+}
+
+void BigInteger::setBit (const int bit)
+{
+ if (bit >= 0)
+ {
+ if (bit > highestBit)
+ {
+ ensureSize (bitToIndex (bit));
+ highestBit = bit;
+ }
+
+ values [bitToIndex (bit)] |= bitToMask (bit);
+ }
+}
+
+void BigInteger::setBit (const int bit, const bool shouldBeSet)
+{
+ if (shouldBeSet)
+ setBit (bit);
+ else
+ clearBit (bit);
+}
+
+void BigInteger::clearBit (const int bit) noexcept
+{
+ if (bit >= 0 && bit <= highestBit)
+ values [bitToIndex (bit)] &= ~bitToMask (bit);
+}
+
+void BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet)
+{
+ while (--numBits >= 0)
+ setBit (startBit++, shouldBeSet);
+}
+
+void BigInteger::insertBit (const int bit, const bool shouldBeSet)
+{
+ if (bit >= 0)
+ shiftBits (1, bit);
+
+ setBit (bit, shouldBeSet);
+}
+
+//==============================================================================
+bool BigInteger::isZero() const noexcept
+{
+ return getHighestBit() < 0;
+}
+
+bool BigInteger::isOne() const noexcept
+{
+ return getHighestBit() == 0 && ! negative;
+}
+
+bool BigInteger::isNegative() const noexcept
+{
+ return negative && ! isZero();
+}
+
+void BigInteger::setNegative (const bool neg) noexcept
+{
+ negative = neg;
+}
+
+void BigInteger::negate() noexcept
+{
+ negative = (! negative) && ! isZero();
+}
+
+#if JUCE_USE_INTRINSICS && ! defined (__INTEL_COMPILER)
+ #pragma intrinsic (_BitScanReverse)
+#endif
+
+inline static int highestBitInInt (uint32 n) noexcept
+{
+ jassert (n != 0); // (the built-in functions may not work for n = 0)
+
+ #if JUCE_GCC
+ return 31 - __builtin_clz (n);
+ #elif JUCE_USE_INTRINSICS
+ unsigned long highest;
+ _BitScanReverse (&highest, n);
+ return (int) highest;
+ #else
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+ return countBitsInInt32 (n >> 1);
+ #endif
+}
+
+int BigInteger::countNumberOfSetBits() const noexcept
+{
+ int total = 0;
+
+ for (int i = (int) bitToIndex (highestBit) + 1; --i >= 0;)
+ total += countNumberOfBits (values[i]);
+
+ return total;
+}
+
+int BigInteger::getHighestBit() const noexcept
+{
+ for (int i = (int) bitToIndex (highestBit + 1); i >= 0; --i)
+ {
+ const uint32 n = values[i];
+
+ if (n != 0)
+ return highestBitInInt (n) + (i << 5);
+ }
+
+ return -1;
+}
+
+int BigInteger::findNextSetBit (int i) const noexcept
+{
+ for (; i <= highestBit; ++i)
+ if ((values [bitToIndex (i)] & bitToMask (i)) != 0)
+ return i;
+
+ return -1;
+}
+
+int BigInteger::findNextClearBit (int i) const noexcept
+{
+ for (; i <= highestBit; ++i)
+ if ((values [bitToIndex (i)] & bitToMask (i)) == 0)
+ break;
+
+ return i;
+}
+
+//==============================================================================
+BigInteger& BigInteger::operator+= (const BigInteger& other)
+{
+ if (other.isNegative())
+ return operator-= (-other);
+
+ if (isNegative())
+ {
+ if (compareAbsolute (other) < 0)
+ {
+ BigInteger temp (*this);
+ temp.negate();
+ *this = other;
+ operator-= (temp);
+ }
+ else
+ {
+ negate();
+ operator-= (other);
+ negate();
+ }
+ }
+ else
+ {
+ if (other.highestBit > highestBit)
+ highestBit = other.highestBit;
+
+ ++highestBit;
+
+ const size_t numInts = bitToIndex (highestBit) + 1;
+ ensureSize (numInts);
+
+ int64 remainder = 0;
+
+ for (size_t i = 0; i <= numInts; ++i)
+ {
+ if (i < numValues)
+ remainder += values[i];
+
+ if (i < other.numValues)
+ remainder += other.values[i];
+
+ values[i] = (uint32) remainder;
+ remainder >>= 32;
+ }
+
+ jassert (remainder == 0);
+ highestBit = getHighestBit();
+ }
+
+ return *this;
+}
+
+BigInteger& BigInteger::operator-= (const BigInteger& other)
+{
+ if (other.isNegative())
+ return operator+= (-other);
+
+ if (! isNegative())
+ {
+ if (compareAbsolute (other) < 0)
+ {
+ BigInteger temp (other);
+ swapWith (temp);
+ operator-= (temp);
+ negate();
+ return *this;
+ }
+ }
+ else
+ {
+ negate();
+ operator+= (other);
+ negate();
+ return *this;
+ }
+
+ const size_t numInts = bitToIndex (highestBit) + 1;
+ const size_t maxOtherInts = bitToIndex (other.highestBit) + 1;
+ int64 amountToSubtract = 0;
+
+ for (size_t i = 0; i <= numInts; ++i)
+ {
+ if (i <= maxOtherInts)
+ amountToSubtract += (int64) other.values[i];
+
+ if (values[i] >= amountToSubtract)
+ {
+ values[i] = (uint32) (values[i] - amountToSubtract);
+ amountToSubtract = 0;
+ }
+ else
+ {
+ const int64 n = ((int64) values[i] + (((int64) 1) << 32)) - amountToSubtract;
+ values[i] = (uint32) n;
+ amountToSubtract = 1;
+ }
+ }
+
+ return *this;
+}
+
+BigInteger& BigInteger::operator*= (const BigInteger& other)
+{
+ BigInteger total;
+ highestBit = getHighestBit();
+ const bool wasNegative = isNegative();
+ setNegative (false);
+
+ for (int i = 0; i <= highestBit; ++i)
+ {
+ if (operator[](i))
+ {
+ BigInteger n (other);
+ n.setNegative (false);
+ n <<= i;
+ total += n;
+ }
+ }
+
+ total.setNegative (wasNegative ^ other.isNegative());
+ swapWith (total);
+ return *this;
+}
+
+void BigInteger::divideBy (const BigInteger& divisor, BigInteger& remainder)
+{
+ jassert (this != &remainder); // (can't handle passing itself in to get the remainder)
+
+ const int divHB = divisor.getHighestBit();
+ const int ourHB = getHighestBit();
+
+ if (divHB < 0 || ourHB < 0)
+ {
+ // division by zero
+ remainder.clear();
+ clear();
+ }
+ else
+ {
+ const bool wasNegative = isNegative();
+
+ swapWith (remainder);
+ remainder.setNegative (false);
+ clear();
+
+ BigInteger temp (divisor);
+ temp.setNegative (false);
+
+ int leftShift = ourHB - divHB;
+ temp <<= leftShift;
+
+ while (leftShift >= 0)
+ {
+ if (remainder.compareAbsolute (temp) >= 0)
+ {
+ remainder -= temp;
+ setBit (leftShift);
+ }
+
+ if (--leftShift >= 0)
+ temp >>= 1;
+ }
+
+ negative = wasNegative ^ divisor.isNegative();
+ remainder.setNegative (wasNegative);
+ }
+}
+
+BigInteger& BigInteger::operator/= (const BigInteger& other)
+{
+ BigInteger remainder;
+ divideBy (other, remainder);
+ return *this;
+}
+
+BigInteger& BigInteger::operator|= (const BigInteger& other)
+{
+ // this operation doesn't take into account negative values..
+ jassert (isNegative() == other.isNegative());
+
+ if (other.highestBit >= 0)
+ {
+ ensureSize (bitToIndex (other.highestBit));
+
+ int n = (int) bitToIndex (other.highestBit) + 1;
+
+ while (--n >= 0)
+ values[n] |= other.values[n];
+
+ if (other.highestBit > highestBit)
+ highestBit = other.highestBit;
+
+ highestBit = getHighestBit();
+ }
+
+ return *this;
+}
+
+BigInteger& BigInteger::operator&= (const BigInteger& other)
+{
+ // this operation doesn't take into account negative values..
+ jassert (isNegative() == other.isNegative());
+
+ int n = (int) numValues;
+
+ while (n > (int) other.numValues)
+ values[--n] = 0;
+
+ while (--n >= 0)
+ values[n] &= other.values[n];
+
+ if (other.highestBit < highestBit)
+ highestBit = other.highestBit;
+
+ highestBit = getHighestBit();
+ return *this;
+}
+
+BigInteger& BigInteger::operator^= (const BigInteger& other)
+{
+ // this operation will only work with the absolute values
+ jassert (isNegative() == other.isNegative());
+
+ if (other.highestBit >= 0)
+ {
+ ensureSize (bitToIndex (other.highestBit));
+
+ int n = (int) bitToIndex (other.highestBit) + 1;
+
+ while (--n >= 0)
+ values[n] ^= other.values[n];
+
+ if (other.highestBit > highestBit)
+ highestBit = other.highestBit;
+
+ highestBit = getHighestBit();
+ }
+
+ return *this;
+}
+
+BigInteger& BigInteger::operator%= (const BigInteger& divisor)
+{
+ BigInteger remainder;
+ divideBy (divisor, remainder);
+ swapWith (remainder);
+ return *this;
+}
+
+BigInteger& BigInteger::operator++() { return operator+= (1); }
+BigInteger& BigInteger::operator--() { return operator-= (1); }
+BigInteger BigInteger::operator++ (int) { const BigInteger old (*this); operator+= (1); return old; }
+BigInteger BigInteger::operator-- (int) { const BigInteger old (*this); operator-= (1); return old; }
+
+BigInteger BigInteger::operator-() const { BigInteger b (*this); b.negate(); return b; }
+BigInteger BigInteger::operator+ (const BigInteger& other) const { BigInteger b (*this); return b += other; }
+BigInteger BigInteger::operator- (const BigInteger& other) const { BigInteger b (*this); return b -= other; }
+BigInteger BigInteger::operator* (const BigInteger& other) const { BigInteger b (*this); return b *= other; }
+BigInteger BigInteger::operator/ (const BigInteger& other) const { BigInteger b (*this); return b /= other; }
+BigInteger BigInteger::operator| (const BigInteger& other) const { BigInteger b (*this); return b |= other; }
+BigInteger BigInteger::operator& (const BigInteger& other) const { BigInteger b (*this); return b &= other; }
+BigInteger BigInteger::operator^ (const BigInteger& other) const { BigInteger b (*this); return b ^= other; }
+BigInteger BigInteger::operator% (const BigInteger& other) const { BigInteger b (*this); return b %= other; }
+BigInteger BigInteger::operator<< (const int numBits) const { BigInteger b (*this); return b <<= numBits; }
+BigInteger BigInteger::operator>> (const int numBits) const { BigInteger b (*this); return b >>= numBits; }
+BigInteger& BigInteger::operator<<= (const int numBits) { shiftBits (numBits, 0); return *this; }
+BigInteger& BigInteger::operator>>= (const int numBits) { shiftBits (-numBits, 0); return *this; }
+
+//==============================================================================
+int BigInteger::compare (const BigInteger& other) const noexcept
+{
+ if (isNegative() == other.isNegative())
+ {
+ const int absComp = compareAbsolute (other);
+ return isNegative() ? -absComp : absComp;
+ }
+ else
+ {
+ return isNegative() ? -1 : 1;
+ }
+}
+
+int BigInteger::compareAbsolute (const BigInteger& other) const noexcept
+{
+ const int h1 = getHighestBit();
+ const int h2 = other.getHighestBit();
+
+ if (h1 > h2)
+ return 1;
+ else if (h1 < h2)
+ return -1;
+
+ for (int i = (int) bitToIndex (h1) + 1; --i >= 0;)
+ if (values[i] != other.values[i])
+ return (values[i] > other.values[i]) ? 1 : -1;
+
+ return 0;
+}
+
+bool BigInteger::operator== (const BigInteger& other) const noexcept { return compare (other) == 0; }
+bool BigInteger::operator!= (const BigInteger& other) const noexcept { return compare (other) != 0; }
+bool BigInteger::operator< (const BigInteger& other) const noexcept { return compare (other) < 0; }
+bool BigInteger::operator<= (const BigInteger& other) const noexcept { return compare (other) <= 0; }
+bool BigInteger::operator> (const BigInteger& other) const noexcept { return compare (other) > 0; }
+bool BigInteger::operator>= (const BigInteger& other) const noexcept { return compare (other) >= 0; }
+
+//==============================================================================
+void BigInteger::shiftLeft (int bits, const int startBit)
+{
+ if (startBit > 0)
+ {
+ for (int i = highestBit + 1; --i >= startBit;)
+ setBit (i + bits, operator[] (i));
+
+ while (--bits >= 0)
+ clearBit (bits + startBit);
+ }
+ else
+ {
+ ensureSize (bitToIndex (highestBit + bits) + 1);
+
+ const size_t wordsToMove = bitToIndex (bits);
+ size_t top = 1 + bitToIndex (highestBit);
+ highestBit += bits;
+
+ if (wordsToMove > 0)
+ {
+ for (int i = (int) top; --i >= 0;)
+ values [(size_t) i + wordsToMove] = values [i];
+
+ for (size_t j = 0; j < wordsToMove; ++j)
+ values [j] = 0;
+
+ bits &= 31;
+ }
+
+ if (bits != 0)
+ {
+ const int invBits = 32 - bits;
+
+ for (size_t i = top + 1 + wordsToMove; --i > wordsToMove;)
+ values[i] = (values[i] << bits) | (values [i - 1] >> invBits);
+
+ values [wordsToMove] = values [wordsToMove] << bits;
+ }
+
+ highestBit = getHighestBit();
+ }
+}
+
+void BigInteger::shiftRight (int bits, const int startBit)
+{
+ if (startBit > 0)
+ {
+ for (int i = startBit; i <= highestBit; ++i)
+ setBit (i, operator[] (i + bits));
+
+ highestBit = getHighestBit();
+ }
+ else
+ {
+ if (bits > highestBit)
+ {
+ clear();
+ }
+ else
+ {
+ const size_t wordsToMove = bitToIndex (bits);
+ size_t top = 1 + bitToIndex (highestBit) - wordsToMove;
+ highestBit -= bits;
+
+ if (wordsToMove > 0)
+ {
+ size_t i;
+ for (i = 0; i < top; ++i)
+ values [i] = values [i + wordsToMove];
+
+ for (i = 0; i < wordsToMove; ++i)
+ values [top + i] = 0;
+
+ bits &= 31;
+ }
+
+ if (bits != 0)
+ {
+ const int invBits = 32 - bits;
+
+ --top;
+ for (size_t i = 0; i < top; ++i)
+ values[i] = (values[i] >> bits) | (values [i + 1] << invBits);
+
+ values[top] = (values[top] >> bits);
+ }
+
+ highestBit = getHighestBit();
+ }
+ }
+}
+
+void BigInteger::shiftBits (int bits, const int startBit)
+{
+ if (highestBit >= 0)
+ {
+ if (bits < 0)
+ shiftRight (-bits, startBit);
+ else if (bits > 0)
+ shiftLeft (bits, startBit);
+ }
+}
+
+//==============================================================================
+static BigInteger simpleGCD (BigInteger* m, BigInteger* n)
+{
+ while (! m->isZero())
+ {
+ if (n->compareAbsolute (*m) > 0)
+ std::swap (m, n);
+
+ *m -= *n;
+ }
+
+ return *n;
+}
+
+BigInteger BigInteger::findGreatestCommonDivisor (BigInteger n) const
+{
+ BigInteger m (*this);
+
+ while (! n.isZero())
+ {
+ if (abs (m.getHighestBit() - n.getHighestBit()) <= 16)
+ return simpleGCD (&m, &n);
+
+ BigInteger temp2;
+ m.divideBy (n, temp2);
+
+ m.swapWith (n);
+ n.swapWith (temp2);
+ }
+
+ return m;
+}
+
+void BigInteger::exponentModulo (const BigInteger& exponent, const BigInteger& modulus)
+{
+ BigInteger exp (exponent);
+ exp %= modulus;
+
+ BigInteger value (1);
+ swapWith (value);
+ value %= modulus;
+
+ while (! exp.isZero())
+ {
+ if (exp [0])
+ {
+ operator*= (value);
+ operator%= (modulus);
+ }
+
+ value *= value;
+ value %= modulus;
+ exp >>= 1;
+ }
+}
+
+void BigInteger::inverseModulo (const BigInteger& modulus)
+{
+ if (modulus.isOne() || modulus.isNegative())
+ {
+ clear();
+ return;
+ }
+
+ if (isNegative() || compareAbsolute (modulus) >= 0)
+ operator%= (modulus);
+
+ if (isOne())
+ return;
+
+ if (! (*this)[0])
+ {
+ // not invertible
+ clear();
+ return;
+ }
+
+ BigInteger a1 (modulus);
+ BigInteger a2 (*this);
+ BigInteger b1 (modulus);
+ BigInteger b2 (1);
+
+ while (! a2.isOne())
+ {
+ BigInteger temp1, multiplier (a1);
+ multiplier.divideBy (a2, temp1);
+
+ temp1 = a2;
+ temp1 *= multiplier;
+ BigInteger temp2 (a1);
+ temp2 -= temp1;
+ a1 = a2;
+ a2 = temp2;
+
+ temp1 = b2;
+ temp1 *= multiplier;
+ temp2 = b1;
+ temp2 -= temp1;
+ b1 = b2;
+ b2 = temp2;
+ }
+
+ while (b2.isNegative())
+ b2 += modulus;
+
+ b2 %= modulus;
+ swapWith (b2);
+}
+
+//==============================================================================
+OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value)
+{
+ return stream << value.toString (10);
+}
+
+String BigInteger::toString (const int base, const int minimumNumCharacters) const
+{
+ String s;
+ BigInteger v (*this);
+
+ if (base == 2 || base == 8 || base == 16)
+ {
+ const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4);
+ static const char hexDigits[] = "0123456789abcdef";
+
+ for (;;)
+ {
+ const uint32 remainder = v.getBitRangeAsInt (0, bits);
+
+ v >>= bits;
+
+ if (remainder == 0 && v.isZero())
+ break;
+
+ s = String::charToString ((juce_wchar) (uint8) hexDigits [remainder]) + s;
+ }
+ }
+ else if (base == 10)
+ {
+ const BigInteger ten (10);
+ BigInteger remainder;
+
+ for (;;)
+ {
+ v.divideBy (ten, remainder);
+
+ if (remainder.isZero() && v.isZero())
+ break;
+
+ s = String (remainder.getBitRangeAsInt (0, 8)) + s;
+ }
+ }
+ else
+ {
+ jassertfalse; // can't do the specified base!
+ return String();
+ }
+
+ s = s.paddedLeft ('0', minimumNumCharacters);
+
+ return isNegative() ? "-" + s : s;
+}
+
+void BigInteger::parseString (StringRef text, const int base)
+{
+ clear();
+ String::CharPointerType t (text.text.findEndOfWhitespace());
+
+ setNegative (*t == (juce_wchar) '-');
+
+ if (base == 2 || base == 8 || base == 16)
+ {
+ const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4);
+
+ for (;;)
+ {
+ const juce_wchar c = t.getAndAdvance();
+ const int digit = CharacterFunctions::getHexDigitValue (c);
+
+ if (((uint32) digit) < (uint32) base)
+ {
+ operator<<= (bits);
+ operator+= (digit);
+ }
+ else if (c == 0)
+ {
+ break;
+ }
+ }
+ }
+ else if (base == 10)
+ {
+ const BigInteger ten ((uint32) 10);
+
+ for (;;)
+ {
+ const juce_wchar c = t.getAndAdvance();
+
+ if (c >= '0' && c <= '9')
+ {
+ operator*= (ten);
+ operator+= ((int) (c - '0'));
+ }
+ else if (c == 0)
+ {
+ break;
+ }
+ }
+ }
+}
+
+MemoryBlock BigInteger::toMemoryBlock() const
+{
+ const int numBytes = (getHighestBit() + 8) >> 3;
+ MemoryBlock mb ((size_t) numBytes);
+
+ for (int i = 0; i < numBytes; ++i)
+ mb[i] = (char) getBitRangeAsInt (i << 3, 8);
+
+ return mb;
+}
+
+void BigInteger::loadFromMemoryBlock (const MemoryBlock& data)
+{
+ clear();
+
+ for (int i = (int) data.getSize(); --i >= 0;)
+ this->setBitRangeAsInt (i << 3, 8, (uint32) data [i]);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.h b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.h
new file mode 100644
index 0000000..4c6c25c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_BigInteger.h
@@ -0,0 +1,334 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_BIGINTEGER_H_INCLUDED
+#define JUCE_BIGINTEGER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ An arbitrarily large integer class.
+
+ A BigInteger can be used in a similar way to a normal integer, but has no size
+ limit (except for memory and performance constraints).
+
+ Negative values are possible, but the value isn't stored as 2s-complement, so
+ be careful if you use negative values and look at the values of individual bits.
+*/
+class JUCE_API BigInteger
+{
+public:
+ //==============================================================================
+ /** Creates an empty BigInteger */
+ BigInteger();
+
+ /** Creates a BigInteger containing an integer value in its low bits.
+ The low 32 bits of the number are initialised with this value.
+ */
+ BigInteger (uint32 value);
+
+ /** Creates a BigInteger containing an integer value in its low bits.
+ The low 32 bits of the number are initialised with the absolute value
+ passed in, and its sign is set to reflect the sign of the number.
+ */
+ BigInteger (int32 value);
+
+ /** Creates a BigInteger containing an integer value in its low bits.
+ The low 64 bits of the number are initialised with the absolute value
+ passed in, and its sign is set to reflect the sign of the number.
+ */
+ BigInteger (int64 value);
+
+ /** Creates a copy of another BigInteger. */
+ BigInteger (const BigInteger&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ BigInteger (BigInteger&&) noexcept;
+ BigInteger& operator= (BigInteger&&) noexcept;
+ #endif
+
+ /** Destructor. */
+ ~BigInteger();
+
+ //==============================================================================
+ /** Copies another BigInteger onto this one. */
+ BigInteger& operator= (const BigInteger&);
+
+ /** Swaps the internal contents of this with another object. */
+ void swapWith (BigInteger&) noexcept;
+
+ //==============================================================================
+ /** Returns the value of a specified bit in the number.
+ If the index is out-of-range, the result will be false.
+ */
+ bool operator[] (int bit) const noexcept;
+
+ /** Returns true if no bits are set. */
+ bool isZero() const noexcept;
+
+ /** Returns true if the value is 1. */
+ bool isOne() const noexcept;
+
+ /** Attempts to get the lowest 32 bits of the value as an integer.
+ If the value is bigger than the integer limits, this will return only the lower bits.
+ */
+ int toInteger() const noexcept;
+
+ /** Attempts to get the lowest 64 bits of the value as an integer.
+ If the value is bigger than the integer limits, this will return only the lower bits.
+ */
+ int64 toInt64() const noexcept;
+
+ //==============================================================================
+ /** Resets the value to 0. */
+ void clear();
+
+ /** Clears a particular bit in the number. */
+ void clearBit (int bitNumber) noexcept;
+
+ /** Sets a specified bit to 1. */
+ void setBit (int bitNumber);
+
+ /** Sets or clears a specified bit. */
+ void setBit (int bitNumber, bool shouldBeSet);
+
+ /** Sets a range of bits to be either on or off.
+
+ @param startBit the first bit to change
+ @param numBits the number of bits to change
+ @param shouldBeSet whether to turn these bits on or off
+ */
+ void setRange (int startBit, int numBits, bool shouldBeSet);
+
+ /** Inserts a bit an a given position, shifting up any bits above it. */
+ void insertBit (int bitNumber, bool shouldBeSet);
+
+ /** Returns a range of bits as a new BigInteger.
+
+ e.g. getBitRangeAsInt (0, 64) would return the lowest 64 bits.
+ @see getBitRangeAsInt
+ */
+ BigInteger getBitRange (int startBit, int numBits) const;
+
+ /** Returns a range of bits as an integer value.
+
+ e.g. getBitRangeAsInt (0, 32) would return the lowest 32 bits.
+
+ Asking for more than 32 bits isn't allowed (obviously) - for that, use
+ getBitRange().
+ */
+ uint32 getBitRangeAsInt (int startBit, int numBits) const noexcept;
+
+ /** Sets a range of bits to an integer value.
+
+ Copies the given integer onto a range of bits, starting at startBit,
+ and using up to numBits of the available bits.
+ */
+ void setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);
+
+ /** Shifts a section of bits left or right.
+
+ @param howManyBitsLeft how far to move the bits (+ve numbers shift it left, -ve numbers shift it right).
+ @param startBit the first bit to affect - if this is > 0, only bits above that index will be affected.
+ */
+ void shiftBits (int howManyBitsLeft, int startBit);
+
+ /** Returns the total number of set bits in the value. */
+ int countNumberOfSetBits() const noexcept;
+
+ /** Looks for the index of the next set bit after a given starting point.
+
+ This searches from startIndex (inclusive) upwards for the first set bit,
+ and returns its index. If no set bits are found, it returns -1.
+ */
+ int findNextSetBit (int startIndex) const noexcept;
+
+ /** Looks for the index of the next clear bit after a given starting point.
+
+ This searches from startIndex (inclusive) upwards for the first clear bit,
+ and returns its index.
+ */
+ int findNextClearBit (int startIndex) const noexcept;
+
+ /** Returns the index of the highest set bit in the number.
+ If the value is zero, this will return -1.
+ */
+ int getHighestBit() const noexcept;
+
+ //==============================================================================
+ // All the standard arithmetic ops...
+
+ BigInteger& operator+= (const BigInteger&);
+ BigInteger& operator-= (const BigInteger&);
+ BigInteger& operator*= (const BigInteger&);
+ BigInteger& operator/= (const BigInteger&);
+ BigInteger& operator|= (const BigInteger&);
+ BigInteger& operator&= (const BigInteger&);
+ BigInteger& operator^= (const BigInteger&);
+ BigInteger& operator%= (const BigInteger&);
+ BigInteger& operator<<= (int numBitsToShift);
+ BigInteger& operator>>= (int numBitsToShift);
+ BigInteger& operator++();
+ BigInteger& operator--();
+ BigInteger operator++ (int);
+ BigInteger operator-- (int);
+
+ BigInteger operator-() const;
+ BigInteger operator+ (const BigInteger&) const;
+ BigInteger operator- (const BigInteger&) const;
+ BigInteger operator* (const BigInteger&) const;
+ BigInteger operator/ (const BigInteger&) const;
+ BigInteger operator| (const BigInteger&) const;
+ BigInteger operator& (const BigInteger&) const;
+ BigInteger operator^ (const BigInteger&) const;
+ BigInteger operator% (const BigInteger&) const;
+ BigInteger operator<< (int numBitsToShift) const;
+ BigInteger operator>> (int numBitsToShift) const;
+
+ bool operator== (const BigInteger&) const noexcept;
+ bool operator!= (const BigInteger&) const noexcept;
+ bool operator< (const BigInteger&) const noexcept;
+ bool operator<= (const BigInteger&) const noexcept;
+ bool operator> (const BigInteger&) const noexcept;
+ bool operator>= (const BigInteger&) const noexcept;
+
+ //==============================================================================
+ /** Does a signed comparison of two BigIntegers.
+
+ Return values are:
+ - 0 if the numbers are the same
+ - < 0 if this number is smaller than the other
+ - > 0 if this number is bigger than the other
+ */
+ int compare (const BigInteger& other) const noexcept;
+
+ /** Compares the magnitudes of two BigIntegers, ignoring their signs.
+
+ Return values are:
+ - 0 if the numbers are the same
+ - < 0 if this number is smaller than the other
+ - > 0 if this number is bigger than the other
+ */
+ int compareAbsolute (const BigInteger& other) const noexcept;
+
+ /** Divides this value by another one and returns the remainder.
+
+ This number is divided by other, leaving the quotient in this number,
+ with the remainder being copied to the other BigInteger passed in.
+ */
+ void divideBy (const BigInteger& divisor, BigInteger& remainder);
+
+ /** Returns the largest value that will divide both this value and the one passed-in. */
+ BigInteger findGreatestCommonDivisor (BigInteger other) const;
+
+ /** Performs a combined exponent and modulo operation.
+ This BigInteger's value becomes (this ^ exponent) % modulus.
+ */
+ void exponentModulo (const BigInteger& exponent, const BigInteger& modulus);
+
+ /** Performs an inverse modulo on the value.
+ i.e. the result is (this ^ -1) mod (modulus).
+ */
+ void inverseModulo (const BigInteger& modulus);
+
+ //==============================================================================
+ /** Returns true if the value is less than zero.
+ @see setNegative, negate
+ */
+ bool isNegative() const noexcept;
+
+ /** Changes the sign of the number to be positive or negative.
+ @see isNegative, negate
+ */
+ void setNegative (bool shouldBeNegative) noexcept;
+
+ /** Inverts the sign of the number.
+ @see isNegative, setNegative
+ */
+ void negate() noexcept;
+
+ //==============================================================================
+ /** Converts the number to a string.
+
+ Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
+ If minimumNumCharacters is greater than 0, the returned string will be
+ padded with leading zeros to reach at least that length.
+ */
+ String toString (int base, int minimumNumCharacters = 1) const;
+
+ /** Reads the numeric value from a string.
+
+ Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
+ Any invalid characters will be ignored.
+ */
+ void parseString (StringRef text, int base);
+
+ //==============================================================================
+ /** Turns the number into a block of binary data.
+
+ The data is arranged as little-endian, so the first byte of data is the low 8 bits
+ of the number, and so on.
+
+ @see loadFromMemoryBlock
+ */
+ MemoryBlock toMemoryBlock() const;
+
+ /** Converts a block of raw data into a number.
+
+ The data is arranged as little-endian, so the first byte of data is the low 8 bits
+ of the number, and so on.
+
+ @see toMemoryBlock
+ */
+ void loadFromMemoryBlock (const MemoryBlock& data);
+
+private:
+ //==============================================================================
+ HeapBlock<uint32> values;
+ size_t numValues;
+ int highestBit;
+ bool negative;
+
+ void ensureSize (size_t);
+ void shiftLeft (int bits, int startBit);
+ void shiftRight (int bits, int startBit);
+
+ JUCE_LEAK_DETECTOR (BigInteger)
+};
+
+/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */
+OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value);
+
+//==============================================================================
+#ifndef DOXYGEN
+ // For backwards compatibility, BitArray is defined as an alias for BigInteger.
+ typedef BigInteger BitArray;
+#endif
+
+
+#endif // JUCE_BIGINTEGER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.cpp
new file mode 100644
index 0000000..a18effa
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.cpp
@@ -0,0 +1,1183 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class Expression::Term : public SingleThreadedReferenceCountedObject
+{
+public:
+ Term() {}
+ virtual ~Term() {}
+
+ virtual Type getType() const noexcept = 0;
+ virtual Term* clone() const = 0;
+ virtual ReferenceCountedObjectPtr<Term> resolve (const Scope&, int recursionDepth) = 0;
+ virtual String toString() const = 0;
+ virtual double toDouble() const { return 0; }
+ virtual int getInputIndexFor (const Term*) const { return -1; }
+ virtual int getOperatorPrecedence() const { return 0; }
+ virtual int getNumInputs() const { return 0; }
+ virtual Term* getInput (int) const { return nullptr; }
+ virtual ReferenceCountedObjectPtr<Term> negated();
+
+ virtual ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const Scope&, const Term* /*inputTerm*/,
+ double /*overallTarget*/, Term* /*topLevelTerm*/) const
+ {
+ jassertfalse;
+ return ReferenceCountedObjectPtr<Term>();
+ }
+
+ virtual String getName() const
+ {
+ jassertfalse; // You shouldn't call this for an expression that's not actually a function!
+ return String();
+ }
+
+ virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
+ {
+ for (int i = getNumInputs(); --i >= 0;)
+ getInput (i)->renameSymbol (oldSymbol, newName, scope, recursionDepth);
+ }
+
+ class SymbolVisitor
+ {
+ public:
+ virtual ~SymbolVisitor() {}
+ virtual void useSymbol (const Symbol&) = 0;
+ };
+
+ virtual void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
+ {
+ for (int i = getNumInputs(); --i >= 0;)
+ getInput(i)->visitAllSymbols (visitor, scope, recursionDepth);
+ }
+
+private:
+ JUCE_DECLARE_NON_COPYABLE (Term)
+};
+
+
+//==============================================================================
+struct Expression::Helpers
+{
+ typedef ReferenceCountedObjectPtr<Term> TermPtr;
+
+ static void checkRecursionDepth (const int depth)
+ {
+ if (depth > 256)
+ throw EvaluationError ("Recursive symbol references");
+ }
+
+ friend class Expression::Term;
+
+ //==============================================================================
+ /** An exception that can be thrown by Expression::evaluate(). */
+ class EvaluationError : public std::exception
+ {
+ public:
+ EvaluationError (const String& desc) : description (desc)
+ {
+ DBG ("Expression::EvaluationError: " + description);
+ }
+
+ String description;
+ };
+
+ //==============================================================================
+ class Constant : public Term
+ {
+ public:
+ Constant (const double val, const bool resolutionTarget)
+ : value (val), isResolutionTarget (resolutionTarget) {}
+
+ Type getType() const noexcept { return constantType; }
+ Term* clone() const { return new Constant (value, isResolutionTarget); }
+ TermPtr resolve (const Scope&, int) { return this; }
+ double toDouble() const { return value; }
+ TermPtr negated() { return new Constant (-value, isResolutionTarget); }
+
+ String toString() const
+ {
+ String s (value);
+ if (isResolutionTarget)
+ s = "@" + s;
+
+ return s;
+ }
+
+ double value;
+ bool isResolutionTarget;
+ };
+
+ //==============================================================================
+ class BinaryTerm : public Term
+ {
+ public:
+ BinaryTerm (Term* const l, Term* const r) : left (l), right (r)
+ {
+ jassert (l != nullptr && r != nullptr);
+ }
+
+ int getInputIndexFor (const Term* possibleInput) const
+ {
+ return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1);
+ }
+
+ Type getType() const noexcept { return operatorType; }
+ int getNumInputs() const { return 2; }
+ Term* getInput (int index) const { return index == 0 ? left.get() : (index == 1 ? right.get() : 0); }
+
+ virtual double performFunction (double left, double right) const = 0;
+ virtual void writeOperator (String& dest) const = 0;
+
+ TermPtr resolve (const Scope& scope, int recursionDepth)
+ {
+ return new Constant (performFunction (left ->resolve (scope, recursionDepth)->toDouble(),
+ right->resolve (scope, recursionDepth)->toDouble()), false);
+ }
+
+ String toString() const
+ {
+ String s;
+
+ const int ourPrecendence = getOperatorPrecedence();
+ if (left->getOperatorPrecedence() > ourPrecendence)
+ s << '(' << left->toString() << ')';
+ else
+ s = left->toString();
+
+ writeOperator (s);
+
+ if (right->getOperatorPrecedence() >= ourPrecendence)
+ s << '(' << right->toString() << ')';
+ else
+ s << right->toString();
+
+ return s;
+ }
+
+ protected:
+ const TermPtr left, right;
+
+ TermPtr createDestinationTerm (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
+ {
+ jassert (input == left || input == right);
+ if (input != left && input != right)
+ return TermPtr();
+
+ if (const Term* const dest = findDestinationFor (topLevelTerm, this))
+ return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm);
+
+ return new Constant (overallTarget, false);
+ }
+ };
+
+ //==============================================================================
+ class SymbolTerm : public Term
+ {
+ public:
+ explicit SymbolTerm (const String& sym) : symbol (sym) {}
+
+ TermPtr resolve (const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+ return scope.getSymbolValue (symbol).term->resolve (scope, recursionDepth + 1);
+ }
+
+ Type getType() const noexcept { return symbolType; }
+ Term* clone() const { return new SymbolTerm (symbol); }
+ String toString() const { return symbol; }
+ String getName() const { return symbol; }
+
+ void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+ visitor.useSymbol (Symbol (scope.getScopeUID(), symbol));
+ scope.getSymbolValue (symbol).term->visitAllSymbols (visitor, scope, recursionDepth + 1);
+ }
+
+ void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int /*recursionDepth*/)
+ {
+ if (oldSymbol.symbolName == symbol && scope.getScopeUID() == oldSymbol.scopeUID)
+ symbol = newName;
+ }
+
+ String symbol;
+ };
+
+ //==============================================================================
+ class Function : public Term
+ {
+ public:
+ explicit Function (const String& name) : functionName (name) {}
+
+ Function (const String& name, const Array<Expression>& params)
+ : functionName (name), parameters (params)
+ {}
+
+ Type getType() const noexcept { return functionType; }
+ Term* clone() const { return new Function (functionName, parameters); }
+ int getNumInputs() const { return parameters.size(); }
+ Term* getInput (int i) const { return parameters.getReference(i).term; }
+ String getName() const { return functionName; }
+
+ TermPtr resolve (const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+ double result = 0;
+ const int numParams = parameters.size();
+ if (numParams > 0)
+ {
+ HeapBlock<double> params ((size_t) numParams);
+ for (int i = 0; i < numParams; ++i)
+ params[i] = parameters.getReference(i).term->resolve (scope, recursionDepth + 1)->toDouble();
+
+ result = scope.evaluateFunction (functionName, params, numParams);
+ }
+ else
+ {
+ result = scope.evaluateFunction (functionName, nullptr, 0);
+ }
+
+ return new Constant (result, false);
+ }
+
+ int getInputIndexFor (const Term* possibleInput) const
+ {
+ for (int i = 0; i < parameters.size(); ++i)
+ if (parameters.getReference(i).term == possibleInput)
+ return i;
+
+ return -1;
+ }
+
+ String toString() const
+ {
+ if (parameters.size() == 0)
+ return functionName + "()";
+
+ String s (functionName + " (");
+
+ for (int i = 0; i < parameters.size(); ++i)
+ {
+ s << parameters.getReference(i).term->toString();
+
+ if (i < parameters.size() - 1)
+ s << ", ";
+ }
+
+ s << ')';
+ return s;
+ }
+
+ const String functionName;
+ Array<Expression> parameters;
+ };
+
+ //==============================================================================
+ class DotOperator : public BinaryTerm
+ {
+ public:
+ DotOperator (SymbolTerm* const l, Term* const r) : BinaryTerm (l, r) {}
+
+ TermPtr resolve (const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+
+ EvaluationVisitor visitor (right, recursionDepth + 1);
+ scope.visitRelativeScope (getSymbol()->symbol, visitor);
+ return visitor.output;
+ }
+
+ Term* clone() const { return new DotOperator (getSymbol(), right); }
+ String getName() const { return "."; }
+ int getOperatorPrecedence() const { return 1; }
+ void writeOperator (String& dest) const { dest << '.'; }
+ double performFunction (double, double) const { return 0.0; }
+
+ void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+ visitor.useSymbol (Symbol (scope.getScopeUID(), getSymbol()->symbol));
+
+ SymbolVisitingVisitor v (right, visitor, recursionDepth + 1);
+
+ try
+ {
+ scope.visitRelativeScope (getSymbol()->symbol, v);
+ }
+ catch (...) {}
+ }
+
+ void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
+ {
+ checkRecursionDepth (recursionDepth);
+ getSymbol()->renameSymbol (oldSymbol, newName, scope, recursionDepth);
+
+ SymbolRenamingVisitor visitor (right, oldSymbol, newName, recursionDepth + 1);
+
+ try
+ {
+ scope.visitRelativeScope (getSymbol()->symbol, visitor);
+ }
+ catch (...) {}
+ }
+
+ private:
+ //==============================================================================
+ class EvaluationVisitor : public Scope::Visitor
+ {
+ public:
+ EvaluationVisitor (const TermPtr& t, const int recursion)
+ : input (t), output (t), recursionCount (recursion) {}
+
+ void visit (const Scope& scope) { output = input->resolve (scope, recursionCount); }
+
+ const TermPtr input;
+ TermPtr output;
+ const int recursionCount;
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (EvaluationVisitor)
+ };
+
+ class SymbolVisitingVisitor : public Scope::Visitor
+ {
+ public:
+ SymbolVisitingVisitor (const TermPtr& t, SymbolVisitor& v, const int recursion)
+ : input (t), visitor (v), recursionCount (recursion) {}
+
+ void visit (const Scope& scope) { input->visitAllSymbols (visitor, scope, recursionCount); }
+
+ private:
+ const TermPtr input;
+ SymbolVisitor& visitor;
+ const int recursionCount;
+
+ JUCE_DECLARE_NON_COPYABLE (SymbolVisitingVisitor)
+ };
+
+ class SymbolRenamingVisitor : public Scope::Visitor
+ {
+ public:
+ SymbolRenamingVisitor (const TermPtr& t, const Expression::Symbol& symbol_, const String& newName_, const int recursionCount_)
+ : input (t), symbol (symbol_), newName (newName_), recursionCount (recursionCount_) {}
+
+ void visit (const Scope& scope) { input->renameSymbol (symbol, newName, scope, recursionCount); }
+
+ private:
+ const TermPtr input;
+ const Symbol& symbol;
+ const String newName;
+ const int recursionCount;
+
+ JUCE_DECLARE_NON_COPYABLE (SymbolRenamingVisitor)
+ };
+
+ SymbolTerm* getSymbol() const { return static_cast <SymbolTerm*> (left.get()); }
+
+ JUCE_DECLARE_NON_COPYABLE (DotOperator)
+ };
+
+ //==============================================================================
+ class Negate : public Term
+ {
+ public:
+ explicit Negate (const TermPtr& t) : input (t)
+ {
+ jassert (t != nullptr);
+ }
+
+ Type getType() const noexcept { return operatorType; }
+ int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; }
+ int getNumInputs() const { return 1; }
+ Term* getInput (int index) const { return index == 0 ? input.get() : nullptr; }
+ Term* clone() const { return new Negate (input->clone()); }
+
+ TermPtr resolve (const Scope& scope, int recursionDepth)
+ {
+ return new Constant (-input->resolve (scope, recursionDepth)->toDouble(), false);
+ }
+
+ String getName() const { return "-"; }
+ TermPtr negated() { return input; }
+
+ TermPtr createTermToEvaluateInput (const Scope& scope, const Term* t, double overallTarget, Term* topLevelTerm) const
+ {
+ (void) t;
+ jassert (t == input);
+
+ const Term* const dest = findDestinationFor (topLevelTerm, this);
+
+ return new Negate (dest == nullptr ? new Constant (overallTarget, false)
+ : dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm));
+ }
+
+ String toString() const
+ {
+ if (input->getOperatorPrecedence() > 0)
+ return "-(" + input->toString() + ")";
+
+ return "-" + input->toString();
+ }
+
+ private:
+ const TermPtr input;
+ };
+
+ //==============================================================================
+ class Add : public BinaryTerm
+ {
+ public:
+ Add (Term* const l, Term* const r) : BinaryTerm (l, r) {}
+
+ Term* clone() const { return new Add (left->clone(), right->clone()); }
+ double performFunction (double lhs, double rhs) const { return lhs + rhs; }
+ int getOperatorPrecedence() const { return 3; }
+ String getName() const { return "+"; }
+ void writeOperator (String& dest) const { dest << " + "; }
+
+ TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
+ {
+ const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
+ if (newDest == nullptr)
+ return TermPtr();
+
+ return new Subtract (newDest, (input == left ? right : left)->clone());
+ }
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (Add)
+ };
+
+ //==============================================================================
+ class Subtract : public BinaryTerm
+ {
+ public:
+ Subtract (Term* const l, Term* const r) : BinaryTerm (l, r) {}
+
+ Term* clone() const { return new Subtract (left->clone(), right->clone()); }
+ double performFunction (double lhs, double rhs) const { return lhs - rhs; }
+ int getOperatorPrecedence() const { return 3; }
+ String getName() const { return "-"; }
+ void writeOperator (String& dest) const { dest << " - "; }
+
+ TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
+ {
+ const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
+ if (newDest == nullptr)
+ return TermPtr();
+
+ if (input == left)
+ return new Add (newDest, right->clone());
+
+ return new Subtract (left->clone(), newDest);
+ }
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (Subtract)
+ };
+
+ //==============================================================================
+ class Multiply : public BinaryTerm
+ {
+ public:
+ Multiply (Term* const l, Term* const r) : BinaryTerm (l, r) {}
+
+ Term* clone() const { return new Multiply (left->clone(), right->clone()); }
+ double performFunction (double lhs, double rhs) const { return lhs * rhs; }
+ String getName() const { return "*"; }
+ void writeOperator (String& dest) const { dest << " * "; }
+ int getOperatorPrecedence() const { return 2; }
+
+ TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
+ {
+ const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
+ if (newDest == nullptr)
+ return TermPtr();
+
+ return new Divide (newDest, (input == left ? right : left)->clone());
+ }
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (Multiply)
+ };
+
+ //==============================================================================
+ class Divide : public BinaryTerm
+ {
+ public:
+ Divide (Term* const l, Term* const r) : BinaryTerm (l, r) {}
+
+ Term* clone() const { return new Divide (left->clone(), right->clone()); }
+ double performFunction (double lhs, double rhs) const { return lhs / rhs; }
+ String getName() const { return "/"; }
+ void writeOperator (String& dest) const { dest << " / "; }
+ int getOperatorPrecedence() const { return 2; }
+
+ TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
+ {
+ const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
+ if (newDest == nullptr)
+ return TermPtr();
+
+ if (input == left)
+ return new Multiply (newDest, right->clone());
+
+ return new Divide (left->clone(), newDest);
+ }
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (Divide)
+ };
+
+ //==============================================================================
+ static Term* findDestinationFor (Term* const topLevel, const Term* const inputTerm)
+ {
+ const int inputIndex = topLevel->getInputIndexFor (inputTerm);
+ if (inputIndex >= 0)
+ return topLevel;
+
+ for (int i = topLevel->getNumInputs(); --i >= 0;)
+ {
+ Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);
+
+ if (t != nullptr)
+ return t;
+ }
+
+ return nullptr;
+ }
+
+ static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
+ {
+ jassert (term != nullptr);
+
+ if (term->getType() == constantType)
+ {
+ Constant* const c = static_cast<Constant*> (term);
+ if (c->isResolutionTarget || ! mustBeFlagged)
+ return c;
+ }
+
+ if (term->getType() == functionType)
+ return nullptr;
+
+ const int numIns = term->getNumInputs();
+
+ for (int i = 0; i < numIns; ++i)
+ {
+ Term* const input = term->getInput (i);
+
+ if (input->getType() == constantType)
+ {
+ Constant* const c = static_cast<Constant*> (input);
+
+ if (c->isResolutionTarget || ! mustBeFlagged)
+ return c;
+ }
+ }
+
+ for (int i = 0; i < numIns; ++i)
+ {
+ Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged);
+ if (c != nullptr)
+ return c;
+ }
+
+ return nullptr;
+ }
+
+ static bool containsAnySymbols (const Term* const t)
+ {
+ if (t->getType() == Expression::symbolType)
+ return true;
+
+ for (int i = t->getNumInputs(); --i >= 0;)
+ if (containsAnySymbols (t->getInput (i)))
+ return true;
+
+ return false;
+ }
+
+ //==============================================================================
+ class SymbolCheckVisitor : public Term::SymbolVisitor
+ {
+ public:
+ SymbolCheckVisitor (const Symbol& symbol_) : wasFound (false), symbol (symbol_) {}
+ void useSymbol (const Symbol& s) { wasFound = wasFound || s == symbol; }
+
+ bool wasFound;
+
+ private:
+ const Symbol& symbol;
+
+ JUCE_DECLARE_NON_COPYABLE (SymbolCheckVisitor)
+ };
+
+ //==============================================================================
+ class SymbolListVisitor : public Term::SymbolVisitor
+ {
+ public:
+ SymbolListVisitor (Array<Symbol>& list_) : list (list_) {}
+ void useSymbol (const Symbol& s) { list.addIfNotAlreadyThere (s); }
+
+ private:
+ Array<Symbol>& list;
+
+ JUCE_DECLARE_NON_COPYABLE (SymbolListVisitor)
+ };
+
+ //==============================================================================
+ class Parser
+ {
+ public:
+ //==============================================================================
+ Parser (String::CharPointerType& stringToParse)
+ : text (stringToParse)
+ {
+ }
+
+ TermPtr readUpToComma()
+ {
+ if (text.isEmpty())
+ return new Constant (0.0, false);
+
+ const TermPtr e (readExpression());
+
+ if (e == nullptr || ((! readOperator (",")) && ! text.isEmpty()))
+ throw ParseError ("Syntax error: \"" + String (text) + "\"");
+
+ return e;
+ }
+
+ private:
+ String::CharPointerType& text;
+
+ //==============================================================================
+ static inline bool isDecimalDigit (const juce_wchar c) noexcept
+ {
+ return c >= '0' && c <= '9';
+ }
+
+ bool readChar (const juce_wchar required) noexcept
+ {
+ if (*text == required)
+ {
+ ++text;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool readOperator (const char* ops, char* const opType = nullptr) noexcept
+ {
+ text = text.findEndOfWhitespace();
+
+ while (*ops != 0)
+ {
+ if (readChar ((juce_wchar) (uint8) *ops))
+ {
+ if (opType != nullptr)
+ *opType = *ops;
+
+ return true;
+ }
+
+ ++ops;
+ }
+
+ return false;
+ }
+
+ bool readIdentifier (String& identifier) noexcept
+ {
+ text = text.findEndOfWhitespace();
+ String::CharPointerType t (text);
+ int numChars = 0;
+
+ if (t.isLetter() || *t == '_')
+ {
+ ++t;
+ ++numChars;
+
+ while (t.isLetterOrDigit() || *t == '_')
+ {
+ ++t;
+ ++numChars;
+ }
+ }
+
+ if (numChars > 0)
+ {
+ identifier = String (text, (size_t) numChars);
+ text = t;
+ return true;
+ }
+
+ return false;
+ }
+
+ Term* readNumber() noexcept
+ {
+ text = text.findEndOfWhitespace();
+ String::CharPointerType t (text);
+
+ const bool isResolutionTarget = (*t == '@');
+ if (isResolutionTarget)
+ {
+ ++t;
+ t = t.findEndOfWhitespace();
+ text = t;
+ }
+
+ if (*t == '-')
+ {
+ ++t;
+ t = t.findEndOfWhitespace();
+ }
+
+ if (isDecimalDigit (*t) || (*t == '.' && isDecimalDigit (t[1])))
+ return new Constant (CharacterFunctions::readDoubleValue (text), isResolutionTarget);
+
+ return nullptr;
+ }
+
+ TermPtr readExpression()
+ {
+ TermPtr lhs (readMultiplyOrDivideExpression());
+
+ char opType;
+ while (lhs != nullptr && readOperator ("+-", &opType))
+ {
+ TermPtr rhs (readMultiplyOrDivideExpression());
+
+ if (rhs == nullptr)
+ throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
+
+ if (opType == '+')
+ lhs = new Add (lhs, rhs);
+ else
+ lhs = new Subtract (lhs, rhs);
+ }
+
+ return lhs;
+ }
+
+ TermPtr readMultiplyOrDivideExpression()
+ {
+ TermPtr lhs (readUnaryExpression());
+
+ char opType;
+ while (lhs != nullptr && readOperator ("*/", &opType))
+ {
+ TermPtr rhs (readUnaryExpression());
+
+ if (rhs == nullptr)
+ throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
+
+ if (opType == '*')
+ lhs = new Multiply (lhs, rhs);
+ else
+ lhs = new Divide (lhs, rhs);
+ }
+
+ return lhs;
+ }
+
+ TermPtr readUnaryExpression()
+ {
+ char opType;
+ if (readOperator ("+-", &opType))
+ {
+ TermPtr e (readUnaryExpression());
+
+ if (e == nullptr)
+ throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
+
+ if (opType == '-')
+ e = e->negated();
+
+ return e;
+ }
+
+ return readPrimaryExpression();
+ }
+
+ TermPtr readPrimaryExpression()
+ {
+ TermPtr e (readParenthesisedExpression());
+ if (e != nullptr)
+ return e;
+
+ e = readNumber();
+ if (e != nullptr)
+ return e;
+
+ return readSymbolOrFunction();
+ }
+
+ TermPtr readSymbolOrFunction()
+ {
+ String identifier;
+ if (readIdentifier (identifier))
+ {
+ if (readOperator ("(")) // method call...
+ {
+ Function* const f = new Function (identifier);
+ ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)
+
+ TermPtr param (readExpression());
+
+ if (param == nullptr)
+ {
+ if (readOperator (")"))
+ return func.release();
+
+ throw ParseError ("Expected parameters after \"" + identifier + " (\"");
+ }
+
+ f->parameters.add (Expression (param));
+
+ while (readOperator (","))
+ {
+ param = readExpression();
+
+ if (param == nullptr)
+ throw ParseError ("Expected expression after \",\"");
+
+ f->parameters.add (Expression (param));
+ }
+
+ if (readOperator (")"))
+ return func.release();
+
+ throw ParseError ("Expected \")\"");
+ }
+
+ if (readOperator ("."))
+ {
+ TermPtr rhs (readSymbolOrFunction());
+
+ if (rhs == nullptr)
+ throw ParseError ("Expected symbol or function after \".\"");
+
+ if (identifier == "this")
+ return rhs;
+
+ return new DotOperator (new SymbolTerm (identifier), rhs);
+ }
+
+ // just a symbol..
+ jassert (identifier.trim() == identifier);
+ return new SymbolTerm (identifier);
+ }
+
+ return TermPtr();
+ }
+
+ TermPtr readParenthesisedExpression()
+ {
+ if (! readOperator ("("))
+ return TermPtr();
+
+ const TermPtr e (readExpression());
+ if (e == nullptr || ! readOperator (")"))
+ return TermPtr();
+
+ return e;
+ }
+
+ JUCE_DECLARE_NON_COPYABLE (Parser)
+ };
+};
+
+//==============================================================================
+Expression::Expression()
+ : term (new Expression::Helpers::Constant (0, false))
+{
+}
+
+Expression::~Expression()
+{
+}
+
+Expression::Expression (Term* const term_)
+ : term (term_)
+{
+ jassert (term != nullptr);
+}
+
+Expression::Expression (const double constant)
+ : term (new Expression::Helpers::Constant (constant, false))
+{
+}
+
+Expression::Expression (const Expression& other)
+ : term (other.term)
+{
+}
+
+Expression& Expression::operator= (const Expression& other)
+{
+ term = other.term;
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+Expression::Expression (Expression&& other) noexcept
+ : term (static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term))
+{
+}
+
+Expression& Expression::operator= (Expression&& other) noexcept
+{
+ term = static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term);
+ return *this;
+}
+#endif
+
+Expression::Expression (const String& stringToParse)
+{
+ String::CharPointerType text (stringToParse.getCharPointer());
+ Helpers::Parser parser (text);
+ term = parser.readUpToComma();
+}
+
+Expression Expression::parse (String::CharPointerType& stringToParse)
+{
+ Helpers::Parser parser (stringToParse);
+ return Expression (parser.readUpToComma());
+}
+
+double Expression::evaluate() const
+{
+ return evaluate (Expression::Scope());
+}
+
+double Expression::evaluate (const Expression::Scope& scope) const
+{
+ try
+ {
+ return term->resolve (scope, 0)->toDouble();
+ }
+ catch (Helpers::EvaluationError&)
+ {}
+
+ return 0;
+}
+
+double Expression::evaluate (const Scope& scope, String& evaluationError) const
+{
+ try
+ {
+ return term->resolve (scope, 0)->toDouble();
+ }
+ catch (Helpers::EvaluationError& e)
+ {
+ evaluationError = e.description;
+ }
+
+ return 0;
+}
+
+Expression Expression::operator+ (const Expression& other) const { return Expression (new Helpers::Add (term, other.term)); }
+Expression Expression::operator- (const Expression& other) const { return Expression (new Helpers::Subtract (term, other.term)); }
+Expression Expression::operator* (const Expression& other) const { return Expression (new Helpers::Multiply (term, other.term)); }
+Expression Expression::operator/ (const Expression& other) const { return Expression (new Helpers::Divide (term, other.term)); }
+Expression Expression::operator-() const { return Expression (term->negated()); }
+Expression Expression::symbol (const String& symbol) { return Expression (new Helpers::SymbolTerm (symbol)); }
+
+Expression Expression::function (const String& functionName, const Array<Expression>& parameters)
+{
+ return Expression (new Helpers::Function (functionName, parameters));
+}
+
+Expression Expression::adjustedToGiveNewResult (const double targetValue, const Expression::Scope& scope) const
+{
+ ScopedPointer<Term> newTerm (term->clone());
+
+ Helpers::Constant* termToAdjust = Helpers::findTermToAdjust (newTerm, true);
+
+ if (termToAdjust == nullptr)
+ termToAdjust = Helpers::findTermToAdjust (newTerm, false);
+
+ if (termToAdjust == nullptr)
+ {
+ newTerm = new Helpers::Add (newTerm.release(), new Helpers::Constant (0, false));
+ termToAdjust = Helpers::findTermToAdjust (newTerm, false);
+ }
+
+ jassert (termToAdjust != nullptr);
+
+ const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust);
+
+ if (parent == nullptr)
+ {
+ termToAdjust->value = targetValue;
+ }
+ else
+ {
+ const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm));
+
+ if (reverseTerm == nullptr)
+ return Expression (targetValue);
+
+ termToAdjust->value = reverseTerm->resolve (scope, 0)->toDouble();
+ }
+
+ return Expression (newTerm.release());
+}
+
+Expression Expression::withRenamedSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Scope& scope) const
+{
+ jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
+
+ if (oldSymbol.symbolName == newName)
+ return *this;
+
+ Expression e (term->clone());
+ e.term->renameSymbol (oldSymbol, newName, scope, 0);
+ return e;
+}
+
+bool Expression::referencesSymbol (const Expression::Symbol& symbolToCheck, const Scope& scope) const
+{
+ Helpers::SymbolCheckVisitor visitor (symbolToCheck);
+
+ try
+ {
+ term->visitAllSymbols (visitor, scope, 0);
+ }
+ catch (Helpers::EvaluationError&)
+ {}
+
+ return visitor.wasFound;
+}
+
+void Expression::findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const
+{
+ try
+ {
+ Helpers::SymbolListVisitor visitor (results);
+ term->visitAllSymbols (visitor, scope, 0);
+ }
+ catch (Helpers::EvaluationError&)
+ {}
+}
+
+String Expression::toString() const { return term->toString(); }
+bool Expression::usesAnySymbols() const { return Helpers::containsAnySymbols (term); }
+Expression::Type Expression::getType() const noexcept { return term->getType(); }
+String Expression::getSymbolOrFunction() const { return term->getName(); }
+int Expression::getNumInputs() const { return term->getNumInputs(); }
+Expression Expression::getInput (int index) const { return Expression (term->getInput (index)); }
+
+//==============================================================================
+ReferenceCountedObjectPtr<Expression::Term> Expression::Term::negated()
+{
+ return new Helpers::Negate (this);
+}
+
+//==============================================================================
+Expression::ParseError::ParseError (const String& message)
+ : description (message)
+{
+ DBG ("Expression::ParseError: " + message);
+}
+
+//==============================================================================
+Expression::Symbol::Symbol (const String& scopeUID_, const String& symbolName_)
+ : scopeUID (scopeUID_), symbolName (symbolName_)
+{
+}
+
+bool Expression::Symbol::operator== (const Symbol& other) const noexcept
+{
+ return symbolName == other.symbolName && scopeUID == other.scopeUID;
+}
+
+bool Expression::Symbol::operator!= (const Symbol& other) const noexcept
+{
+ return ! operator== (other);
+}
+
+//==============================================================================
+Expression::Scope::Scope() {}
+Expression::Scope::~Scope() {}
+
+Expression Expression::Scope::getSymbolValue (const String& symbol) const
+{
+ if (symbol.isNotEmpty())
+ throw Helpers::EvaluationError ("Unknown symbol: " + symbol);
+
+ return Expression();
+}
+
+double Expression::Scope::evaluateFunction (const String& functionName, const double* parameters, int numParams) const
+{
+ if (numParams > 0)
+ {
+ if (functionName == "min")
+ {
+ double v = parameters[0];
+ for (int i = 1; i < numParams; ++i)
+ v = jmin (v, parameters[i]);
+
+ return v;
+ }
+
+ if (functionName == "max")
+ {
+ double v = parameters[0];
+ for (int i = 1; i < numParams; ++i)
+ v = jmax (v, parameters[i]);
+
+ return v;
+ }
+
+ if (numParams == 1)
+ {
+ if (functionName == "sin") return sin (parameters[0]);
+ if (functionName == "cos") return cos (parameters[0]);
+ if (functionName == "tan") return tan (parameters[0]);
+ if (functionName == "abs") return std::abs (parameters[0]);
+ }
+ }
+
+ throw Helpers::EvaluationError ("Unknown function: \"" + functionName + "\"");
+}
+
+void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) const
+{
+ throw Helpers::EvaluationError ("Unknown symbol: " + scopeName);
+}
+
+String Expression::Scope::getScopeUID() const
+{
+ return String();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.h b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.h
new file mode 100644
index 0000000..8939129
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Expression.h
@@ -0,0 +1,270 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_EXPRESSION_H_INCLUDED
+#define JUCE_EXPRESSION_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A class for dynamically evaluating simple numeric expressions.
+
+ This class can parse a simple C-style string expression involving floating point
+ numbers, named symbols and functions. The basic arithmetic operations of +, -, *, /
+ are supported, as well as parentheses, and any alphanumeric identifiers are
+ assumed to be named symbols which will be resolved when the expression is
+ evaluated.
+
+ Expressions which use identifiers and functions require a subclass of
+ Expression::Scope to be supplied when evaluating them, and this object
+ is expected to be able to resolve the symbol names and perform the functions that
+ are used.
+*/
+class JUCE_API Expression
+{
+public:
+ //==============================================================================
+ /** Creates a simple expression with a value of 0. */
+ Expression();
+
+ /** Destructor. */
+ ~Expression();
+
+ /** Creates a simple expression with a specified constant value. */
+ explicit Expression (double constant);
+
+ /** Creates a copy of an expression. */
+ Expression (const Expression&);
+
+ /** Copies another expression. */
+ Expression& operator= (const Expression&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ Expression (Expression&&) noexcept;
+ Expression& operator= (Expression&&) noexcept;
+ #endif
+
+ /** Creates an expression by parsing a string.
+ If there's a syntax error in the string, this will throw a ParseError exception.
+ @throws ParseError
+ */
+ explicit Expression (const String& stringToParse);
+
+ /** Returns a string version of the expression. */
+ String toString() const;
+
+ /** Returns an expression which is an addition operation of two existing expressions. */
+ Expression operator+ (const Expression&) const;
+ /** Returns an expression which is a subtraction operation of two existing expressions. */
+ Expression operator- (const Expression&) const;
+ /** Returns an expression which is a multiplication operation of two existing expressions. */
+ Expression operator* (const Expression&) const;
+ /** Returns an expression which is a division operation of two existing expressions. */
+ Expression operator/ (const Expression&) const;
+ /** Returns an expression which performs a negation operation on an existing expression. */
+ Expression operator-() const;
+
+ /** Returns an Expression which is an identifier reference. */
+ static Expression symbol (const String& symbol);
+
+ /** Returns an Expression which is a function call. */
+ static Expression function (const String& functionName, const Array<Expression>& parameters);
+
+ /** Returns an Expression which parses a string from a character pointer, and updates the pointer
+ to indicate where it finished.
+
+ The pointer is incremented so that on return, it indicates the character that follows
+ the end of the expression that was parsed.
+
+ If there's a syntax error in the string, this will throw a ParseError exception.
+ @throws ParseError
+ */
+ static Expression parse (String::CharPointerType& stringToParse);
+
+ //==============================================================================
+ /** When evaluating an Expression object, this class is used to resolve symbols and
+ perform functions that the expression uses.
+ */
+ class JUCE_API Scope
+ {
+ public:
+ Scope();
+ virtual ~Scope();
+
+ /** Returns some kind of globally unique ID that identifies this scope. */
+ virtual String getScopeUID() const;
+
+ /** Returns the value of a symbol.
+ If the symbol is unknown, this can throw an Expression::EvaluationError exception.
+ The member value is set to the part of the symbol that followed the dot, if there is
+ one, e.g. for "foo.bar", symbol = "foo" and member = "bar".
+ @throws Expression::EvaluationError
+ */
+ virtual Expression getSymbolValue (const String& symbol) const;
+
+ /** Executes a named function.
+ If the function name is unknown, this can throw an Expression::EvaluationError exception.
+ @throws Expression::EvaluationError
+ */
+ virtual double evaluateFunction (const String& functionName,
+ const double* parameters, int numParameters) const;
+
+ /** Used as a callback by the Scope::visitRelativeScope() method.
+ You should never create an instance of this class yourself, it's used by the
+ expression evaluation code.
+ */
+ class Visitor
+ {
+ public:
+ virtual ~Visitor() {}
+ virtual void visit (const Scope&) = 0;
+ };
+
+ /** Creates a Scope object for a named scope, and then calls a visitor
+ to do some kind of processing with this new scope.
+
+ If the name is valid, this method must create a suitable (temporary) Scope
+ object to represent it, and must call the Visitor::visit() method with this
+ new scope.
+ */
+ virtual void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
+ };
+
+ /** Evaluates this expression, without using a Scope.
+ Without a Scope, no symbols can be used, and only basic functions such as sin, cos, tan,
+ min, max are available.
+ To find out about any errors during evaluation, use the other version of this method which
+ takes a String parameter.
+ */
+ double evaluate() const;
+
+ /** Evaluates this expression, providing a scope that should be able to evaluate any symbols
+ or functions that it uses.
+ To find out about any errors during evaluation, use the other version of this method which
+ takes a String parameter.
+ */
+ double evaluate (const Scope& scope) const;
+
+ /** Evaluates this expression, providing a scope that should be able to evaluate any symbols
+ or functions that it uses.
+ */
+ double evaluate (const Scope& scope, String& evaluationError) const;
+
+ /** Attempts to return an expression which is a copy of this one, but with a constant adjusted
+ to make the expression resolve to a target value.
+
+ E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return
+ the expression "x + 3". Obviously some expressions can't be reversed in this way, in which
+ case they might just be adjusted by adding a constant to the original expression.
+
+ @throws Expression::EvaluationError
+ */
+ Expression adjustedToGiveNewResult (double targetValue, const Scope& scope) const;
+
+ /** Represents a symbol that is used in an Expression. */
+ struct Symbol
+ {
+ Symbol (const String& scopeUID, const String& symbolName);
+ bool operator== (const Symbol&) const noexcept;
+ bool operator!= (const Symbol&) const noexcept;
+
+ String scopeUID; /**< The unique ID of the Scope that contains this symbol. */
+ String symbolName; /**< The name of the symbol. */
+ };
+
+ /** Returns a copy of this expression in which all instances of a given symbol have been renamed. */
+ Expression withRenamedSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope) const;
+
+ /** Returns true if this expression makes use of the specified symbol.
+ If a suitable scope is supplied, the search will dereference and recursively check
+ all symbols, so that it can be determined whether this expression relies on the given
+ symbol at any level in its evaluation. If the scope parameter is null, this just checks
+ whether the expression contains any direct references to the symbol.
+
+ @throws Expression::EvaluationError
+ */
+ bool referencesSymbol (const Symbol& symbol, const Scope& scope) const;
+
+ /** Returns true if this expression contains any symbols. */
+ bool usesAnySymbols() const;
+
+ /** Returns a list of all symbols that may be needed to resolve this expression in the given scope. */
+ void findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const;
+
+ //==============================================================================
+ /** An exception that can be thrown by Expression::parse(). */
+ class ParseError : public std::exception
+ {
+ public:
+ ParseError (const String& message);
+
+ String description;
+ };
+
+ //==============================================================================
+ /** Expression type.
+ @see Expression::getType()
+ */
+ enum Type
+ {
+ constantType,
+ functionType,
+ operatorType,
+ symbolType
+ };
+
+ /** Returns the type of this expression. */
+ Type getType() const noexcept;
+
+ /** If this expression is a symbol, function or operator, this returns its identifier. */
+ String getSymbolOrFunction() const;
+
+ /** Returns the number of inputs to this expression.
+ @see getInput
+ */
+ int getNumInputs() const;
+
+ /** Retrieves one of the inputs to this expression.
+ @see getNumInputs
+ */
+ Expression getInput (int index) const;
+
+private:
+ //==============================================================================
+ class Term;
+ struct Helpers;
+ friend class Term;
+ friend struct Helpers;
+ friend struct ContainerDeletePolicy<Term>;
+ friend class ReferenceCountedObjectPtr<Term>;
+ ReferenceCountedObjectPtr<Term> term;
+
+ explicit Expression (Term*);
+};
+
+#endif // JUCE_EXPRESSION_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_MathsFunctions.h b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_MathsFunctions.h
new file mode 100644
index 0000000..d2d02b9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_MathsFunctions.h
@@ -0,0 +1,549 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MATHSFUNCTIONS_H_INCLUDED
+#define JUCE_MATHSFUNCTIONS_H_INCLUDED
+
+//==============================================================================
+/*
+ This file sets up some handy mathematical typdefs and functions.
+*/
+
+//==============================================================================
+// Definitions for the int8, int16, int32, int64 and pointer_sized_int types.
+
+/** A platform-independent 8-bit signed integer type. */
+typedef signed char int8;
+/** A platform-independent 8-bit unsigned integer type. */
+typedef unsigned char uint8;
+/** A platform-independent 16-bit signed integer type. */
+typedef signed short int16;
+/** A platform-independent 16-bit unsigned integer type. */
+typedef unsigned short uint16;
+/** A platform-independent 32-bit signed integer type. */
+typedef signed int int32;
+/** A platform-independent 32-bit unsigned integer type. */
+typedef unsigned int uint32;
+
+#if JUCE_MSVC
+ /** A platform-independent 64-bit integer type. */
+ typedef __int64 int64;
+ /** A platform-independent 64-bit unsigned integer type. */
+ typedef unsigned __int64 uint64;
+#else
+ /** A platform-independent 64-bit integer type. */
+ typedef long long int64;
+ /** A platform-independent 64-bit unsigned integer type. */
+ typedef unsigned long long uint64;
+#endif
+
+#ifndef DOXYGEN
+ /** A macro for creating 64-bit literals.
+ Historically, this was needed to support portability with MSVC6, and is kept here
+ so that old code will still compile, but nowadays every compiler will support the
+ LL and ULL suffixes, so you should use those in preference to this macro.
+ */
+ #define literal64bit(longLiteral) (longLiteral##LL)
+#endif
+
+#if JUCE_64BIT
+ /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef int64 pointer_sized_int;
+ /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef uint64 pointer_sized_uint;
+#elif JUCE_MSVC
+ /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef _W64 int pointer_sized_int;
+ /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef _W64 unsigned int pointer_sized_uint;
+#else
+ /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef int pointer_sized_int;
+ /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */
+ typedef unsigned int pointer_sized_uint;
+#endif
+
+#if JUCE_MSVC
+ typedef pointer_sized_int ssize_t;
+#endif
+
+//==============================================================================
+// Some indispensible min/max functions
+
+/** Returns the larger of two values. */
+template <typename Type>
+inline Type jmax (const Type a, const Type b) { return (a < b) ? b : a; }
+
+/** Returns the larger of three values. */
+template <typename Type>
+inline Type jmax (const Type a, const Type b, const Type c) { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
+
+/** Returns the larger of four values. */
+template <typename Type>
+inline Type jmax (const Type a, const Type b, const Type c, const Type d) { return jmax (a, jmax (b, c, d)); }
+
+/** Returns the smaller of two values. */
+template <typename Type>
+inline Type jmin (const Type a, const Type b) { return (b < a) ? b : a; }
+
+/** Returns the smaller of three values. */
+template <typename Type>
+inline Type jmin (const Type a, const Type b, const Type c) { return (b < a) ? ((c < b) ? c : b) : ((c < a) ? c : a); }
+
+/** Returns the smaller of four values. */
+template <typename Type>
+inline Type jmin (const Type a, const Type b, const Type c, const Type d) { return jmin (a, jmin (b, c, d)); }
+
+/** Scans an array of values, returning the minimum value that it contains. */
+template <typename Type>
+const Type findMinimum (const Type* data, int numValues)
+{
+ if (numValues <= 0)
+ return Type();
+
+ Type result (*data++);
+
+ while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
+ {
+ const Type& v = *data++;
+ if (v < result) result = v;
+ }
+
+ return result;
+}
+
+/** Scans an array of values, returning the maximum value that it contains. */
+template <typename Type>
+const Type findMaximum (const Type* values, int numValues)
+{
+ if (numValues <= 0)
+ return Type();
+
+ Type result (*values++);
+
+ while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
+ {
+ const Type& v = *values++;
+ if (result < v) result = v;
+ }
+
+ return result;
+}
+
+/** Scans an array of values, returning the minimum and maximum values that it contains. */
+template <typename Type>
+void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highest)
+{
+ if (numValues <= 0)
+ {
+ lowest = Type();
+ highest = Type();
+ }
+ else
+ {
+ Type mn (*values++);
+ Type mx (mn);
+
+ while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
+ {
+ const Type& v = *values++;
+
+ if (mx < v) mx = v;
+ if (v < mn) mn = v;
+ }
+
+ lowest = mn;
+ highest = mx;
+ }
+}
+
+
+//==============================================================================
+/** Constrains a value to keep it within a given range.
+
+ This will check that the specified value lies between the lower and upper bounds
+ specified, and if not, will return the nearest value that would be in-range. Effectively,
+ it's like calling jmax (lowerLimit, jmin (upperLimit, value)).
+
+ Note that it expects that lowerLimit <= upperLimit. If this isn't true,
+ the results will be unpredictable.
+
+ @param lowerLimit the minimum value to return
+ @param upperLimit the maximum value to return
+ @param valueToConstrain the value to try to return
+ @returns the closest value to valueToConstrain which lies between lowerLimit
+ and upperLimit (inclusive)
+ @see jlimit0To, jmin, jmax
+*/
+template <typename Type>
+inline Type jlimit (const Type lowerLimit,
+ const Type upperLimit,
+ const Type valueToConstrain) noexcept
+{
+ jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable..
+
+ return (valueToConstrain < lowerLimit) ? lowerLimit
+ : ((upperLimit < valueToConstrain) ? upperLimit
+ : valueToConstrain);
+}
+
+/** Returns true if a value is at least zero, and also below a specified upper limit.
+ This is basically a quicker way to write:
+ @code valueToTest >= 0 && valueToTest < upperLimit
+ @endcode
+*/
+template <typename Type>
+inline bool isPositiveAndBelow (Type valueToTest, Type upperLimit) noexcept
+{
+ jassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
+ return Type() <= valueToTest && valueToTest < upperLimit;
+}
+
+template <>
+inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noexcept
+{
+ jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
+ return static_cast <unsigned int> (valueToTest) < static_cast <unsigned int> (upperLimit);
+}
+
+/** Returns true if a value is at least zero, and also less than or equal to a specified upper limit.
+ This is basically a quicker way to write:
+ @code valueToTest >= 0 && valueToTest <= upperLimit
+ @endcode
+*/
+template <typename Type>
+inline bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) noexcept
+{
+ jassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
+ return Type() <= valueToTest && valueToTest <= upperLimit;
+}
+
+template <>
+inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) noexcept
+{
+ jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
+ return static_cast <unsigned int> (valueToTest) <= static_cast <unsigned int> (upperLimit);
+}
+
+//==============================================================================
+/** Handy function to swap two values. */
+template <typename Type>
+inline void swapVariables (Type& variable1, Type& variable2)
+{
+ std::swap (variable1, variable2);
+}
+
+/** Handy function for getting the number of elements in a simple const C array.
+ E.g.
+ @code
+ static int myArray[] = { 1, 2, 3 };
+
+ int numElements = numElementsInArray (myArray) // returns 3
+ @endcode
+*/
+template <typename Type, int N>
+inline int numElementsInArray (Type (&array)[N])
+{
+ (void) array; // (required to avoid a spurious warning in MS compilers)
+ (void) sizeof (0[array]); // This line should cause an error if you pass an object with a user-defined subscript operator
+ return N;
+}
+
+//==============================================================================
+// Some useful maths functions that aren't always present with all compilers and build settings.
+
+/** Using juce_hypot is easier than dealing with the different types of hypot function
+ that are provided by the various platforms and compilers. */
+template <typename Type>
+inline Type juce_hypot (Type a, Type b) noexcept
+{
+ #if JUCE_MSVC
+ return static_cast <Type> (_hypot (a, b));
+ #else
+ return static_cast <Type> (hypot (a, b));
+ #endif
+}
+
+/** 64-bit abs function. */
+inline int64 abs64 (const int64 n) noexcept
+{
+ return (n >= 0) ? n : -n;
+}
+
+#if JUCE_MSVC && ! defined (DOXYGEN) // The MSVC libraries omit these functions for some reason...
+ template<typename Type> Type asinh (Type x) noexcept { return std::log (x + std::sqrt (x * x + (Type) 1)); }
+ template<typename Type> Type acosh (Type x) noexcept { return std::log (x + std::sqrt (x * x - (Type) 1)); }
+ template<typename Type> Type atanh (Type x) noexcept { return (std::log (x + (Type) 1) - std::log (((Type) 1) - x)) / (Type) 2; }
+#endif
+
+//==============================================================================
+/** A predefined value for Pi, at double-precision.
+ @see float_Pi
+*/
+const double double_Pi = 3.1415926535897932384626433832795;
+
+/** A predefined value for Pi, at single-precision.
+ @see double_Pi
+*/
+const float float_Pi = 3.14159265358979323846f;
+
+
+//==============================================================================
+/** The isfinite() method seems to vary between platforms, so this is a
+ platform-independent function for it.
+*/
+template <typename FloatingPointType>
+inline bool juce_isfinite (FloatingPointType value)
+{
+ #if JUCE_WINDOWS
+ return _finite (value);
+ #elif JUCE_ANDROID
+ return isfinite (value);
+ #else
+ return std::isfinite (value);
+ #endif
+}
+
+//==============================================================================
+#if JUCE_MSVC
+ #pragma optimize ("t", off)
+ #ifndef __INTEL_COMPILER
+ #pragma float_control (precise, on, push)
+ #endif
+#endif
+
+/** Fast floating-point-to-integer conversion.
+
+ This is faster than using the normal c++ cast to convert a float to an int, and
+ it will round the value to the nearest integer, rather than rounding it down
+ like the normal cast does.
+
+ Note that this routine gets its speed at the expense of some accuracy, and when
+ rounding values whose floating point component is exactly 0.5, odd numbers and
+ even numbers will be rounded up or down differently.
+*/
+template <typename FloatType>
+inline int roundToInt (const FloatType value) noexcept
+{
+ #ifdef __INTEL_COMPILER
+ #pragma float_control (precise, on, push)
+ #endif
+
+ union { int asInt[2]; double asDouble; } n;
+ n.asDouble = ((double) value) + 6755399441055744.0;
+
+ #if JUCE_BIG_ENDIAN
+ return n.asInt [1];
+ #else
+ return n.asInt [0];
+ #endif
+}
+
+inline int roundToInt (int value) noexcept
+{
+ return value;
+}
+
+#if JUCE_MSVC
+ #ifndef __INTEL_COMPILER
+ #pragma float_control (pop)
+ #endif
+ #pragma optimize ("", on) // resets optimisations to the project defaults
+#endif
+
+/** Fast floating-point-to-integer conversion.
+
+ This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works
+ fine for values above zero, but negative numbers are rounded the wrong way.
+*/
+inline int roundToIntAccurate (const double value) noexcept
+{
+ #ifdef __INTEL_COMPILER
+ #pragma float_control (pop)
+ #endif
+
+ return roundToInt (value + 1.5e-8);
+}
+
+/** Fast floating-point-to-integer conversion.
+
+ This is faster than using the normal c++ cast to convert a double to an int, and
+ it will round the value to the nearest integer, rather than rounding it down
+ like the normal cast does.
+
+ Note that this routine gets its speed at the expense of some accuracy, and when
+ rounding values whose floating point component is exactly 0.5, odd numbers and
+ even numbers will be rounded up or down differently. For a more accurate conversion,
+ see roundDoubleToIntAccurate().
+*/
+inline int roundDoubleToInt (const double value) noexcept
+{
+ return roundToInt (value);
+}
+
+/** Fast floating-point-to-integer conversion.
+
+ This is faster than using the normal c++ cast to convert a float to an int, and
+ it will round the value to the nearest integer, rather than rounding it down
+ like the normal cast does.
+
+ Note that this routine gets its speed at the expense of some accuracy, and when
+ rounding values whose floating point component is exactly 0.5, odd numbers and
+ even numbers will be rounded up or down differently.
+*/
+inline int roundFloatToInt (const float value) noexcept
+{
+ return roundToInt (value);
+}
+
+//==============================================================================
+/** Returns true if the specified integer is a power-of-two.
+*/
+template <typename IntegerType>
+bool isPowerOfTwo (IntegerType value)
+{
+ return (value & (value - 1)) == 0;
+}
+
+/** Returns the smallest power-of-two which is equal to or greater than the given integer.
+*/
+inline int nextPowerOfTwo (int n) noexcept
+{
+ --n;
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+ return n + 1;
+}
+
+/** Returns the number of bits in a 32-bit integer. */
+inline int countNumberOfBits (uint32 n) noexcept
+{
+ n -= ((n >> 1) & 0x55555555);
+ n = (((n >> 2) & 0x33333333) + (n & 0x33333333));
+ n = (((n >> 4) + n) & 0x0f0f0f0f);
+ n += (n >> 8);
+ n += (n >> 16);
+ return (int) (n & 0x3f);
+}
+
+/** Returns the number of bits in a 64-bit integer. */
+inline int countNumberOfBits (uint64 n) noexcept
+{
+ return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32));
+}
+
+/** Performs a modulo operation, but can cope with the dividend being negative.
+ The divisor must be greater than zero.
+*/
+template <typename IntegerType>
+IntegerType negativeAwareModulo (IntegerType dividend, const IntegerType divisor) noexcept
+{
+ jassert (divisor > 0);
+ dividend %= divisor;
+ return (dividend < 0) ? (dividend + divisor) : dividend;
+}
+
+/** Returns the square of its argument. */
+template <typename NumericType>
+NumericType square (NumericType n) noexcept
+{
+ return n * n;
+}
+
+//==============================================================================
+#if (JUCE_INTEL && JUCE_32BIT) || defined (DOXYGEN)
+ /** This macro can be applied to a float variable to check whether it contains a denormalised
+ value, and to normalise it if necessary.
+ On CPUs that aren't vulnerable to denormalisation problems, this will have no effect.
+ */
+ #define JUCE_UNDENORMALISE(x) x += 1.0f; x -= 1.0f;
+#else
+ #define JUCE_UNDENORMALISE(x)
+#endif
+
+//==============================================================================
+/** This namespace contains a few template classes for helping work out class type variations.
+*/
+namespace TypeHelpers
+{
+ #if JUCE_VC8_OR_EARLIER
+ #define PARAMETER_TYPE(type) const type&
+ #else
+ /** The ParameterType struct is used to find the best type to use when passing some kind
+ of object as a parameter.
+
+ Of course, this is only likely to be useful in certain esoteric template situations.
+
+ Because "typename TypeHelpers::ParameterType<SomeClass>::type" is a bit of a mouthful, there's
+ a PARAMETER_TYPE(SomeClass) macro that you can use to get the same effect.
+
+ E.g. "myFunction (PARAMETER_TYPE (int), PARAMETER_TYPE (MyObject))"
+ would evaluate to "myfunction (int, const MyObject&)", keeping any primitive types as
+ pass-by-value, but passing objects as a const reference, to avoid copying.
+ */
+ template <typename Type> struct ParameterType { typedef const Type& type; };
+
+ #if ! DOXYGEN
+ template <typename Type> struct ParameterType <Type&> { typedef Type& type; };
+ template <typename Type> struct ParameterType <Type*> { typedef Type* type; };
+ template <> struct ParameterType <char> { typedef char type; };
+ template <> struct ParameterType <unsigned char> { typedef unsigned char type; };
+ template <> struct ParameterType <short> { typedef short type; };
+ template <> struct ParameterType <unsigned short> { typedef unsigned short type; };
+ template <> struct ParameterType <int> { typedef int type; };
+ template <> struct ParameterType <unsigned int> { typedef unsigned int type; };
+ template <> struct ParameterType <long> { typedef long type; };
+ template <> struct ParameterType <unsigned long> { typedef unsigned long type; };
+ template <> struct ParameterType <int64> { typedef int64 type; };
+ template <> struct ParameterType <uint64> { typedef uint64 type; };
+ template <> struct ParameterType <bool> { typedef bool type; };
+ template <> struct ParameterType <float> { typedef float type; };
+ template <> struct ParameterType <double> { typedef double type; };
+ #endif
+
+ /** A helpful macro to simplify the use of the ParameterType template.
+ @see ParameterType
+ */
+ #define PARAMETER_TYPE(a) typename TypeHelpers::ParameterType<a>::type
+ #endif
+
+
+ /** These templates are designed to take a type, and if it's a double, they return a double
+ type; for anything else, they return a float type.
+ */
+ template <typename Type> struct SmallestFloatType { typedef float type; };
+ template <> struct SmallestFloatType <double> { typedef double type; };
+}
+
+
+//==============================================================================
+
+#endif // JUCE_MATHSFUNCTIONS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.cpp
new file mode 100644
index 0000000..a196256
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.cpp
@@ -0,0 +1,189 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Random::Random (const int64 seedValue) noexcept : seed (seedValue)
+{
+}
+
+Random::Random() : seed (1)
+{
+ setSeedRandomly();
+}
+
+Random::~Random() noexcept
+{
+}
+
+void Random::setSeed (const int64 newSeed) noexcept
+{
+ seed = newSeed;
+}
+
+void Random::combineSeed (const int64 seedValue) noexcept
+{
+ seed ^= nextInt64() ^ seedValue;
+}
+
+void Random::setSeedRandomly()
+{
+ static int64 globalSeed = 0;
+
+ combineSeed (globalSeed ^ (int64) (pointer_sized_int) this);
+ combineSeed (Time::getMillisecondCounter());
+ combineSeed (Time::getHighResolutionTicks());
+ combineSeed (Time::getHighResolutionTicksPerSecond());
+ combineSeed (Time::currentTimeMillis());
+ globalSeed ^= seed;
+}
+
+Random& Random::getSystemRandom() noexcept
+{
+ static Random sysRand;
+ return sysRand;
+}
+
+//==============================================================================
+int Random::nextInt() noexcept
+{
+ seed = (seed * 0x5deece66dLL + 11) & 0xffffffffffffLL;
+
+ return (int) (seed >> 16);
+}
+
+int Random::nextInt (const int maxValue) noexcept
+{
+ jassert (maxValue > 0);
+ return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32);
+}
+
+int Random::nextInt (Range<int> range) noexcept
+{
+ return range.getStart() + nextInt (range.getLength());
+}
+
+int64 Random::nextInt64() noexcept
+{
+ return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt();
+}
+
+bool Random::nextBool() noexcept
+{
+ return (nextInt() & 0x40000000) != 0;
+}
+
+float Random::nextFloat() noexcept
+{
+ return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0f);
+}
+
+double Random::nextDouble() noexcept
+{
+ return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0);
+}
+
+BigInteger Random::nextLargeNumber (const BigInteger& maximumValue)
+{
+ BigInteger n;
+
+ do
+ {
+ fillBitsRandomly (n, 0, maximumValue.getHighestBit() + 1);
+ }
+ while (n >= maximumValue);
+
+ return n;
+}
+
+void Random::fillBitsRandomly (void* const buffer, size_t bytes)
+{
+ int* d = static_cast<int*> (buffer);
+
+ for (; bytes >= sizeof (int); bytes -= sizeof (int))
+ *d++ = nextInt();
+
+ if (bytes > 0)
+ {
+ const int lastBytes = nextInt();
+ memcpy (d, &lastBytes, bytes);
+ }
+}
+
+void Random::fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits)
+{
+ arrayToChange.setBit (startBit + numBits - 1, true); // to force the array to pre-allocate space
+
+ while ((startBit & 31) != 0 && numBits > 0)
+ {
+ arrayToChange.setBit (startBit++, nextBool());
+ --numBits;
+ }
+
+ while (numBits >= 32)
+ {
+ arrayToChange.setBitRangeAsInt (startBit, 32, (unsigned int) nextInt());
+ startBit += 32;
+ numBits -= 32;
+ }
+
+ while (--numBits >= 0)
+ arrayToChange.setBit (startBit + numBits, nextBool());
+}
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class RandomTests : public UnitTest
+{
+public:
+ RandomTests() : UnitTest ("Random") {}
+
+ void runTest()
+ {
+ beginTest ("Random");
+
+ Random r = getRandom();
+
+ for (int i = 2000; --i >= 0;)
+ {
+ expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
+ expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
+ expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
+ expect (r.nextInt (1) == 0);
+
+ int n = r.nextInt (50) + 1;
+ expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
+
+ n = r.nextInt (0x7ffffffe) + 1;
+ expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
+ }
+ }
+};
+
+static RandomTests randomTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.h b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.h
new file mode 100644
index 0000000..19e6d6e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Random.h
@@ -0,0 +1,143 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_RANDOM_H_INCLUDED
+#define JUCE_RANDOM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A random number generator.
+
+ You can create a Random object and use it to generate a sequence of random numbers.
+*/
+class JUCE_API Random
+{
+public:
+ //==============================================================================
+ /** Creates a Random object based on a seed value.
+
+ For a given seed value, the subsequent numbers generated by this object
+ will be predictable, so a good idea is to set this value based
+ on the time, e.g.
+
+ new Random (Time::currentTimeMillis())
+ */
+ explicit Random (int64 seedValue) noexcept;
+
+ /** Creates a Random object using a random seed value.
+ Internally, this calls setSeedRandomly() to randomise the seed.
+ */
+ Random();
+
+ /** Destructor. */
+ ~Random() noexcept;
+
+ /** Returns the next random 32 bit integer.
+ @returns a random integer from the full range 0x80000000 to 0x7fffffff
+ */
+ int nextInt() noexcept;
+
+ /** Returns the next random number, limited to a given range.
+ The maxValue parameter may not be negative, or zero.
+ @returns a random integer between 0 (inclusive) and maxValue (exclusive).
+ */
+ int nextInt (int maxValue) noexcept;
+
+ /** Returns the next random number, limited to a given range.
+ @returns a random integer between the range start (inclusive) and its end (exclusive).
+ */
+ int nextInt (Range<int> range) noexcept;
+
+ /** Returns the next 64-bit random number.
+ @returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
+ */
+ int64 nextInt64() noexcept;
+
+ /** Returns the next random floating-point number.
+ @returns a random value in the range 0 to 1.0
+ */
+ float nextFloat() noexcept;
+
+ /** Returns the next random floating-point number.
+ @returns a random value in the range 0 to 1.0
+ */
+ double nextDouble() noexcept;
+
+ /** Returns the next random boolean value. */
+ bool nextBool() noexcept;
+
+ /** Returns a BigInteger containing a random number.
+ @returns a random value in the range 0 to (maximumValue - 1).
+ */
+ BigInteger nextLargeNumber (const BigInteger& maximumValue);
+
+ /** Fills a block of memory with random values. */
+ void fillBitsRandomly (void* bufferToFill, size_t sizeInBytes);
+
+ /** Sets a range of bits in a BigInteger to random values. */
+ void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits);
+
+ //==============================================================================
+ /** Resets this Random object to a given seed value. */
+ void setSeed (int64 newSeed) noexcept;
+
+ /** Returns the RNG's current seed. */
+ int64 getSeed() const noexcept { return seed; }
+
+ /** Merges this object's seed with another value.
+ This sets the seed to be a value created by combining the current seed and this
+ new value.
+ */
+ void combineSeed (int64 seedValue) noexcept;
+
+ /** Reseeds this generator using a value generated from various semi-random system
+ properties like the current time, etc.
+
+ Because this function convolves the time with the last seed value, calling
+ it repeatedly will increase the randomness of the final result.
+ */
+ void setSeedRandomly();
+
+ /** The overhead of creating a new Random object is fairly small, but if you want to avoid
+ it, you can call this method to get a global shared Random object.
+
+ It's not thread-safe though, so threads should use their own Random object, otherwise
+ you run the risk of your random numbers becoming.. erm.. randomly corrupted..
+ */
+ static Random& getSystemRandom() noexcept;
+
+private:
+ //==============================================================================
+ int64 seed;
+
+ JUCE_LEAK_DETECTOR (Random)
+};
+
+
+#endif // JUCE_RANDOM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Range.h b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Range.h
new file mode 100644
index 0000000..6add152
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/maths/juce_Range.h
@@ -0,0 +1,304 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_RANGE_H_INCLUDED
+#define JUCE_RANGE_H_INCLUDED
+
+
+//==============================================================================
+/** A general-purpose range object, that simply represents any linear range with
+ a start and end point.
+
+ Note that when checking whether values fall within the range, the start value is
+ considered to be inclusive, and the end of the range exclusive.
+
+ The templated parameter is expected to be a primitive integer or floating point
+ type, though class types could also be used if they behave in a number-like way.
+*/
+template <typename ValueType>
+class Range
+{
+public:
+ //==============================================================================
+ /** Constructs an empty range. */
+ Range() noexcept : start(), end()
+ {
+ }
+
+ /** Constructs a range with given start and end values. */
+ Range (const ValueType startValue, const ValueType endValue) noexcept
+ : start (startValue), end (jmax (startValue, endValue))
+ {
+ }
+
+ /** Constructs a copy of another range. */
+ Range (const Range& other) noexcept
+ : start (other.start), end (other.end)
+ {
+ }
+
+ /** Copies another range object. */
+ Range& operator= (Range other) noexcept
+ {
+ start = other.start;
+ end = other.end;
+ return *this;
+ }
+
+ /** Returns the range that lies between two positions (in either order). */
+ static Range between (const ValueType position1, const ValueType position2) noexcept
+ {
+ return position1 < position2 ? Range (position1, position2)
+ : Range (position2, position1);
+ }
+
+ /** Returns a range with a given start and length. */
+ static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept
+ {
+ jassert (length >= ValueType());
+ return Range (startValue, startValue + length);
+ }
+
+ /** Returns a range with the specified start position and a length of zero. */
+ static Range emptyRange (const ValueType start) noexcept
+ {
+ return Range (start, start);
+ }
+
+ //==============================================================================
+ /** Returns the start of the range. */
+ inline ValueType getStart() const noexcept { return start; }
+
+ /** Returns the length of the range. */
+ inline ValueType getLength() const noexcept { return end - start; }
+
+ /** Returns the end of the range. */
+ inline ValueType getEnd() const noexcept { return end; }
+
+ /** Returns true if the range has a length of zero. */
+ inline bool isEmpty() const noexcept { return start == end; }
+
+ //==============================================================================
+ /** Changes the start position of the range, leaving the end position unchanged.
+ If the new start position is higher than the current end of the range, the end point
+ will be pushed along to equal it, leaving an empty range at the new position.
+ */
+ void setStart (const ValueType newStart) noexcept
+ {
+ start = newStart;
+ if (end < newStart)
+ end = newStart;
+ }
+
+ /** Returns a range with the same end as this one, but a different start.
+ If the new start position is higher than the current end of the range, the end point
+ will be pushed along to equal it, returning an empty range at the new position.
+ */
+ Range withStart (const ValueType newStart) const noexcept
+ {
+ return Range (newStart, jmax (newStart, end));
+ }
+
+ /** Returns a range with the same length as this one, but moved to have the given start position. */
+ Range movedToStartAt (const ValueType newStart) const noexcept
+ {
+ return Range (newStart, end + (newStart - start));
+ }
+
+ /** Changes the end position of the range, leaving the start unchanged.
+ If the new end position is below the current start of the range, the start point
+ will be pushed back to equal the new end point.
+ */
+ void setEnd (const ValueType newEnd) noexcept
+ {
+ end = newEnd;
+ if (newEnd < start)
+ start = newEnd;
+ }
+
+ /** Returns a range with the same start position as this one, but a different end.
+ If the new end position is below the current start of the range, the start point
+ will be pushed back to equal the new end point.
+ */
+ Range withEnd (const ValueType newEnd) const noexcept
+ {
+ return Range (jmin (start, newEnd), newEnd);
+ }
+
+ /** Returns a range with the same length as this one, but moved to have the given end position. */
+ Range movedToEndAt (const ValueType newEnd) const noexcept
+ {
+ return Range (start + (newEnd - end), newEnd);
+ }
+
+ /** Changes the length of the range.
+ Lengths less than zero are treated as zero.
+ */
+ void setLength (const ValueType newLength) noexcept
+ {
+ end = start + jmax (ValueType(), newLength);
+ }
+
+ /** Returns a range with the same start as this one, but a different length.
+ Lengths less than zero are treated as zero.
+ */
+ Range withLength (const ValueType newLength) const noexcept
+ {
+ return Range (start, start + newLength);
+ }
+
+ //==============================================================================
+ /** Adds an amount to the start and end of the range. */
+ inline Range operator+= (const ValueType amountToAdd) noexcept
+ {
+ start += amountToAdd;
+ end += amountToAdd;
+ return *this;
+ }
+
+ /** Subtracts an amount from the start and end of the range. */
+ inline Range operator-= (const ValueType amountToSubtract) noexcept
+ {
+ start -= amountToSubtract;
+ end -= amountToSubtract;
+ return *this;
+ }
+
+ /** Returns a range that is equal to this one with an amount added to its
+ start and end.
+ */
+ Range operator+ (const ValueType amountToAdd) const noexcept
+ {
+ return Range (start + amountToAdd, end + amountToAdd);
+ }
+
+ /** Returns a range that is equal to this one with the specified amount
+ subtracted from its start and end. */
+ Range operator- (const ValueType amountToSubtract) const noexcept
+ {
+ return Range (start - amountToSubtract, end - amountToSubtract);
+ }
+
+ bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
+ bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
+
+ //==============================================================================
+ /** Returns true if the given position lies inside this range. */
+ bool contains (const ValueType position) const noexcept
+ {
+ return start <= position && position < end;
+ }
+
+ /** Returns the nearest value to the one supplied, which lies within the range. */
+ ValueType clipValue (const ValueType value) const noexcept
+ {
+ return jlimit (start, end, value);
+ }
+
+ /** Returns true if the given range lies entirely inside this range.
+ When making this comparison, the start value is considered to be inclusive,
+ and the end of the range exclusive.
+ */
+ bool contains (Range other) const noexcept
+ {
+ return start <= other.start && end >= other.end;
+ }
+
+ /** Returns true if the given range intersects this one. */
+ bool intersects (Range other) const noexcept
+ {
+ return other.start < end && start < other.end;
+ }
+
+ /** Returns the range that is the intersection of the two ranges, or an empty range
+ with an undefined start position if they don't overlap. */
+ Range getIntersectionWith (Range other) const noexcept
+ {
+ return Range (jmax (start, other.start),
+ jmin (end, other.end));
+ }
+
+ /** Returns the smallest range that contains both this one and the other one. */
+ Range getUnionWith (Range other) const noexcept
+ {
+ return Range (jmin (start, other.start),
+ jmax (end, other.end));
+ }
+
+ /** Returns the smallest range that contains both this one and the given value. */
+ Range getUnionWith (const ValueType valueToInclude) const noexcept
+ {
+ return Range (jmin (valueToInclude, start),
+ jmax (valueToInclude, end));
+ }
+
+ /** Returns a given range, after moving it forwards or backwards to fit it
+ within this range.
+
+ If the supplied range has a greater length than this one, the return value
+ will be this range.
+
+ Otherwise, if the supplied range is smaller than this one, the return value
+ will be the new range, shifted forwards or backwards so that it doesn't extend
+ beyond this one, but keeping its original length.
+ */
+ Range constrainRange (Range rangeToConstrain) const noexcept
+ {
+ const ValueType otherLen = rangeToConstrain.getLength();
+ return getLength() <= otherLen
+ ? *this
+ : rangeToConstrain.movedToStartAt (jlimit (start, end - otherLen, rangeToConstrain.getStart()));
+ }
+
+ /** Scans an array of values for its min and max, and returns these as a Range. */
+ static Range findMinAndMax (const ValueType* values, int numValues) noexcept
+ {
+ if (numValues <= 0)
+ return Range();
+
+ const ValueType first (*values++);
+ Range r (first, first);
+
+ while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
+ {
+ const ValueType v (*values++);
+
+ if (r.end < v) r.end = v;
+ if (v < r.start) r.start = v;
+ }
+
+ return r;
+ }
+
+private:
+ //==============================================================================
+ ValueType start, end;
+};
+
+
+#endif // JUCE_RANGE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Atomic.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Atomic.h
new file mode 100644
index 0000000..d0dd6be
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Atomic.h
@@ -0,0 +1,399 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ATOMIC_H_INCLUDED
+#define JUCE_ATOMIC_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Simple class to hold a primitive value and perform atomic operations on it.
+
+ The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
+ There are methods to perform most of the basic atomic operations.
+*/
+template <typename Type>
+class Atomic
+{
+public:
+ /** Creates a new value, initialised to zero. */
+ inline Atomic() noexcept
+ : value (0)
+ {
+ }
+
+ /** Creates a new value, with a given initial value. */
+ inline explicit Atomic (const Type initialValue) noexcept
+ : value (initialValue)
+ {
+ }
+
+ /** Copies another value (atomically). */
+ inline Atomic (const Atomic& other) noexcept
+ : value (other.get())
+ {
+ }
+
+ /** Destructor. */
+ inline ~Atomic() noexcept
+ {
+ // This class can only be used for types which are 32 or 64 bits in size.
+ static_jassert (sizeof (Type) == 4 || sizeof (Type) == 8);
+ }
+
+ /** Atomically reads and returns the current value. */
+ Type get() const noexcept;
+
+ /** Copies another value onto this one (atomically). */
+ inline Atomic& operator= (const Atomic& other) noexcept { exchange (other.get()); return *this; }
+
+ /** Copies another value onto this one (atomically). */
+ inline Atomic& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
+
+ /** Atomically sets the current value. */
+ void set (Type newValue) noexcept { exchange (newValue); }
+
+ /** Atomically sets the current value, returning the value that was replaced. */
+ Type exchange (Type value) noexcept;
+
+ /** Atomically adds a number to this value, returning the new value. */
+ Type operator+= (Type amountToAdd) noexcept;
+
+ /** Atomically subtracts a number from this value, returning the new value. */
+ Type operator-= (Type amountToSubtract) noexcept;
+
+ /** Atomically increments this value, returning the new value. */
+ Type operator++() noexcept;
+
+ /** Atomically decrements this value, returning the new value. */
+ Type operator--() noexcept;
+
+ /** Atomically compares this value with a target value, and if it is equal, sets
+ this to be equal to a new value.
+
+ This operation is the atomic equivalent of doing this:
+ @code
+ bool compareAndSetBool (Type newValue, Type valueToCompare)
+ {
+ if (get() == valueToCompare)
+ {
+ set (newValue);
+ return true;
+ }
+
+ return false;
+ }
+ @endcode
+
+ @returns true if the comparison was true and the value was replaced; false if
+ the comparison failed and the value was left unchanged.
+ @see compareAndSetValue
+ */
+ bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
+
+ /** Atomically compares this value with a target value, and if it is equal, sets
+ this to be equal to a new value.
+
+ This operation is the atomic equivalent of doing this:
+ @code
+ Type compareAndSetValue (Type newValue, Type valueToCompare)
+ {
+ Type oldValue = get();
+ if (oldValue == valueToCompare)
+ set (newValue);
+
+ return oldValue;
+ }
+ @endcode
+
+ @returns the old value before it was changed.
+ @see compareAndSetBool
+ */
+ Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
+
+ /** Implements a memory read/write barrier. */
+ static void memoryBarrier() noexcept;
+
+ //==============================================================================
+ #if JUCE_64BIT
+ JUCE_ALIGN (8)
+ #else
+ JUCE_ALIGN (4)
+ #endif
+
+ /** The raw value that this class operates on.
+ This is exposed publically in case you need to manipulate it directly
+ for performance reasons.
+ */
+ volatile Type value;
+
+private:
+ template <typename Dest, typename Source>
+ static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
+
+ static inline Type castFrom32Bit (int32 value) noexcept { return castTo <Type, int32> (value); }
+ static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
+ static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
+ static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
+
+ Type operator++ (int); // better to just use pre-increment with atomics..
+ Type operator-- (int);
+
+ /** This templated negate function will negate pointers as well as integers */
+ template <typename ValueType>
+ inline ValueType negateValue (ValueType n) noexcept
+ {
+ return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
+ : (sizeof (ValueType) == 2 ? (ValueType) -(short) n
+ : (sizeof (ValueType) == 4 ? (ValueType) -(int) n
+ : ((ValueType) -(int64) n)));
+ }
+
+ /** This templated negate function will negate pointers as well as integers */
+ template <typename PointerType>
+ inline PointerType* negateValue (PointerType* n) noexcept
+ {
+ return reinterpret_cast <PointerType*> (-reinterpret_cast <pointer_sized_int> (n));
+ }
+};
+
+
+//==============================================================================
+/*
+ The following code is in the header so that the atomics can be inlined where possible...
+*/
+#if JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
+ #define JUCE_ATOMICS_MAC_LEGACY 1 // Older OSX builds using gcc4.1 or earlier
+
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ #define JUCE_MAC_ATOMICS_VOLATILE
+ #else
+ #define JUCE_MAC_ATOMICS_VOLATILE volatile
+ #endif
+
+ #if JUCE_PPC
+ // None of these atomics are available for PPC or for iOS 3.1 or earlier!!
+ template <typename Type> static Type OSAtomicAdd64Barrier (Type b, JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return *a += b; }
+ template <typename Type> static Type OSAtomicIncrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return ++*a; }
+ template <typename Type> static Type OSAtomicDecrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return --*a; }
+ template <typename Type> static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, JUCE_MAC_ATOMICS_VOLATILE Type* value) noexcept
+ { jassertfalse; if (old == *value) { *value = newValue; return true; } return false; }
+ #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
+ #endif
+
+//==============================================================================
+#elif JUCE_GCC || JUCE_CLANG
+ #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics
+
+ #if JUCE_IOS || JUCE_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
+ #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
+ #endif
+
+//==============================================================================
+#else
+ #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics
+
+ #if JUCE_USE_INTRINSICS
+ #ifndef __INTEL_COMPILER
+ #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
+ _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
+ #endif
+ #define juce_InterlockedExchange(a, b) _InterlockedExchange(a, b)
+ #define juce_InterlockedIncrement(a) _InterlockedIncrement(a)
+ #define juce_InterlockedDecrement(a) _InterlockedDecrement(a)
+ #define juce_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
+ #define juce_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
+ #define juce_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
+ #define juce_MemoryBarrier _ReadWriteBarrier
+ #else
+ long juce_InterlockedExchange (volatile long* a, long b) noexcept;
+ long juce_InterlockedIncrement (volatile long* a) noexcept;
+ long juce_InterlockedDecrement (volatile long* a) noexcept;
+ long juce_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
+ long juce_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
+ __int64 juce_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
+ inline void juce_MemoryBarrier() noexcept { long x = 0; juce_InterlockedIncrement (&x); }
+ #endif
+
+ #if JUCE_64BIT
+ #ifndef __INTEL_COMPILER
+ #pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
+ #endif
+ #define juce_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
+ #define juce_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
+ #define juce_InterlockedIncrement64(a) _InterlockedIncrement64(a)
+ #define juce_InterlockedDecrement64(a) _InterlockedDecrement64(a)
+ #else
+ // None of these atomics are available in a 32-bit Windows build!!
+ template <typename Type> static Type juce_InterlockedExchangeAdd64 (volatile Type* a, Type b) noexcept { jassertfalse; Type old = *a; *a += b; return old; }
+ template <typename Type> static Type juce_InterlockedExchange64 (volatile Type* a, Type b) noexcept { jassertfalse; Type old = *a; *a = b; return old; }
+ template <typename Type> static Type juce_InterlockedIncrement64 (volatile Type* a) noexcept { jassertfalse; return ++*a; }
+ template <typename Type> static Type juce_InterlockedDecrement64 (volatile Type* a) noexcept { jassertfalse; return --*a; }
+ #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
+ #endif
+#endif
+
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4311) // (truncation warning)
+#endif
+
+//==============================================================================
+template <typename Type>
+inline Type Atomic<Type>::get() const noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value))
+ : castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value));
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
+ : castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0));
+ #elif JUCE_ATOMICS_GCC
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0))
+ : castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0));
+ #endif
+}
+
+template <typename Type>
+inline Type Atomic<Type>::exchange (const Type newValue) noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC
+ Type currentVal = value;
+ while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
+ return currentVal;
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
+ : castFrom64Bit ((int64) juce_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
+ #endif
+}
+
+template <typename Type>
+inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
+ : (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd)
+ : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
+ #elif JUCE_ATOMICS_GCC
+ return (Type) __sync_add_and_fetch (&value, amountToAdd);
+ #endif
+}
+
+template <typename Type>
+inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
+{
+ return operator+= (negateValue (amountToSubtract));
+}
+
+template <typename Type>
+inline Type Atomic<Type>::operator++() noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
+ : (Type) OSAtomicIncrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value)
+ : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value);
+ #elif JUCE_ATOMICS_GCC
+ return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) 1)
+ : (Type) __sync_add_and_fetch ((int64_t*) &value, 1);
+ #endif
+}
+
+template <typename Type>
+inline Type Atomic<Type>::operator--() noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
+ : (Type) OSAtomicDecrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value)
+ : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value);
+ #elif JUCE_ATOMICS_GCC
+ return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) -1)
+ : (Type) __sync_add_and_fetch ((int64_t*) &value, -1);
+ #endif
+}
+
+template <typename Type>
+inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
+ : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
+ #elif JUCE_ATOMICS_WINDOWS
+ return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
+ #elif JUCE_ATOMICS_GCC
+ return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
+ : __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
+ #endif
+}
+
+template <typename Type>
+inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ for (;;) // Annoying workaround for only having a bool CAS operation..
+ {
+ if (compareAndSetBool (newValue, valueToCompare))
+ return valueToCompare;
+
+ const Type result = value;
+ if (result != valueToCompare)
+ return result;
+ }
+
+ #elif JUCE_ATOMICS_WINDOWS
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
+ : castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare)));
+ #elif JUCE_ATOMICS_GCC
+ return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
+ : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
+ #endif
+}
+
+template <typename Type>
+inline void Atomic<Type>::memoryBarrier() noexcept
+{
+ #if JUCE_ATOMICS_MAC_LEGACY
+ OSMemoryBarrier();
+ #elif JUCE_ATOMICS_GCC
+ __sync_synchronize();
+ #elif JUCE_ATOMICS_WINDOWS
+ juce_MemoryBarrier();
+ #endif
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // JUCE_ATOMIC_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ByteOrder.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ByteOrder.h
new file mode 100644
index 0000000..0ecf2e4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ByteOrder.h
@@ -0,0 +1,196 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_BYTEORDER_H_INCLUDED
+#define JUCE_BYTEORDER_H_INCLUDED
+
+
+//==============================================================================
+/** Contains static methods for converting the byte order between different
+ endiannesses.
+*/
+class JUCE_API ByteOrder
+{
+public:
+ //==============================================================================
+ /** Swaps the upper and lower bytes of a 16-bit integer. */
+ static uint16 swap (uint16 value) noexcept;
+
+ /** Reverses the order of the 4 bytes in a 32-bit integer. */
+ static uint32 swap (uint32 value) noexcept;
+
+ /** Reverses the order of the 8 bytes in a 64-bit integer. */
+ static uint64 swap (uint64 value) noexcept;
+
+ //==============================================================================
+ /** Swaps the byte order of a 16-bit int if the CPU is big-endian */
+ static uint16 swapIfBigEndian (uint16 value) noexcept;
+
+ /** Swaps the byte order of a 32-bit int if the CPU is big-endian */
+ static uint32 swapIfBigEndian (uint32 value) noexcept;
+
+ /** Swaps the byte order of a 64-bit int if the CPU is big-endian */
+ static uint64 swapIfBigEndian (uint64 value) noexcept;
+
+ /** Swaps the byte order of a 16-bit int if the CPU is little-endian */
+ static uint16 swapIfLittleEndian (uint16 value) noexcept;
+
+ /** Swaps the byte order of a 32-bit int if the CPU is little-endian */
+ static uint32 swapIfLittleEndian (uint32 value) noexcept;
+
+ /** Swaps the byte order of a 64-bit int if the CPU is little-endian */
+ static uint64 swapIfLittleEndian (uint64 value) noexcept;
+
+ //==============================================================================
+ /** Turns 4 bytes into a little-endian integer. */
+ static uint32 littleEndianInt (const void* bytes) noexcept;
+
+ /** Turns 8 bytes into a little-endian integer. */
+ static uint64 littleEndianInt64 (const void* bytes) noexcept;
+
+ /** Turns 2 bytes into a little-endian integer. */
+ static uint16 littleEndianShort (const void* bytes) noexcept;
+
+ /** Turns 4 bytes into a big-endian integer. */
+ static uint32 bigEndianInt (const void* bytes) noexcept;
+
+ /** Turns 8 bytes into a big-endian integer. */
+ static uint64 bigEndianInt64 (const void* bytes) noexcept;
+
+ /** Turns 2 bytes into a big-endian integer. */
+ static uint16 bigEndianShort (const void* bytes) noexcept;
+
+ //==============================================================================
+ /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
+ static int littleEndian24Bit (const void* bytes) noexcept;
+
+ /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
+ static int bigEndian24Bit (const void* bytes) noexcept;
+
+ /** Copies a 24-bit number to 3 little-endian bytes. */
+ static void littleEndian24BitToChars (int value, void* destBytes) noexcept;
+
+ /** Copies a 24-bit number to 3 big-endian bytes. */
+ static void bigEndian24BitToChars (int value, void* destBytes) noexcept;
+
+ //==============================================================================
+ /** Returns true if the current CPU is big-endian. */
+ static bool isBigEndian() noexcept;
+
+private:
+ ByteOrder() JUCE_DELETED_FUNCTION;
+
+ JUCE_DECLARE_NON_COPYABLE (ByteOrder)
+};
+
+
+//==============================================================================
+#if JUCE_USE_INTRINSICS && ! defined (__INTEL_COMPILER)
+ #pragma intrinsic (_byteswap_ulong)
+#endif
+
+inline uint16 ByteOrder::swap (uint16 n) noexcept
+{
+ #if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic!
+ return static_cast<uint16> (_byteswap_ushort (n));
+ #else
+ return static_cast<uint16> ((n << 8) | (n >> 8));
+ #endif
+}
+
+inline uint32 ByteOrder::swap (uint32 n) noexcept
+{
+ #if JUCE_MAC || JUCE_IOS
+ return OSSwapInt32 (n);
+ #elif JUCE_GCC && JUCE_INTEL && ! JUCE_NO_INLINE_ASM
+ asm("bswap %%eax" : "=a"(n) : "a"(n));
+ return n;
+ #elif JUCE_USE_INTRINSICS
+ return _byteswap_ulong (n);
+ #elif JUCE_MSVC && ! JUCE_NO_INLINE_ASM
+ __asm {
+ mov eax, n
+ bswap eax
+ mov n, eax
+ }
+ return n;
+ #elif JUCE_ANDROID
+ return bswap_32 (n);
+ #else
+ return (n << 24) | (n >> 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8);
+ #endif
+}
+
+inline uint64 ByteOrder::swap (uint64 value) noexcept
+{
+ #if JUCE_MAC || JUCE_IOS
+ return OSSwapInt64 (value);
+ #elif JUCE_USE_INTRINSICS
+ return _byteswap_uint64 (value);
+ #else
+ return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32));
+ #endif
+}
+
+#if JUCE_LITTLE_ENDIAN
+ inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return v; }
+ inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return v; }
+ inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return v; }
+ inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return swap (v); }
+ inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return swap (v); }
+ inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return swap (v); }
+ inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); }
+ inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); }
+ inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); }
+ inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); }
+ inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); }
+ inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); }
+ inline bool ByteOrder::isBigEndian() noexcept { return false; }
+#else
+ inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return swap (v); }
+ inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return swap (v); }
+ inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return swap (v); }
+ inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return v; }
+ inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return v; }
+ inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return v; }
+ inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); }
+ inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); }
+ inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); }
+ inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); }
+ inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); }
+ inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); }
+ inline bool ByteOrder::isBigEndian() noexcept { return true; }
+#endif
+
+inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[2]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[0]); }
+inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[0]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[2]); }
+inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) value; static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) (value >> 16); }
+inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) (value >> 16); static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) value; }
+
+
+#endif // JUCE_BYTEORDER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ContainerDeletePolicy.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ContainerDeletePolicy.h
new file mode 100644
index 0000000..60cddaa
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ContainerDeletePolicy.h
@@ -0,0 +1,53 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
+#define JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
+
+//==============================================================================
+/**
+ Used by container classes as an indirect way to delete an object of a
+ particular type.
+
+ The generic implementation of this class simply calls 'delete', but you can
+ create a specialised version of it for a particular class if you need to
+ delete that type of object in a more appropriate way.
+
+ @see ScopedPointer, OwnedArray
+*/
+template <typename ObjectType>
+struct ContainerDeletePolicy
+{
+ static void destroy (ObjectType* object)
+ {
+ delete object;
+ }
+};
+
+
+#endif // JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_HeapBlock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_HeapBlock.h
new file mode 100644
index 0000000..3731f0b
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_HeapBlock.h
@@ -0,0 +1,308 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_HEAPBLOCK_H_INCLUDED
+#define JUCE_HEAPBLOCK_H_INCLUDED
+
+#ifndef DOXYGEN
+namespace HeapBlockHelper
+{
+ template <bool shouldThrow>
+ struct ThrowOnFail { static void check (void*) {} };
+
+ template<>
+ struct ThrowOnFail <true> { static void check (void* data) { if (data == nullptr) throw std::bad_alloc(); } };
+}
+#endif
+
+//==============================================================================
+/**
+ Very simple container class to hold a pointer to some data on the heap.
+
+ When you need to allocate some heap storage for something, always try to use
+ this class instead of allocating the memory directly using malloc/free.
+
+ A HeapBlock<char> object can be treated in pretty much exactly the same way
+ as an char*, but as long as you allocate it on the stack or as a class member,
+ it's almost impossible for it to leak memory.
+
+ It also makes your code much more concise and readable than doing the same thing
+ using direct allocations,
+
+ E.g. instead of this:
+ @code
+ int* temp = (int*) malloc (1024 * sizeof (int));
+ memcpy (temp, xyz, 1024 * sizeof (int));
+ free (temp);
+ temp = (int*) calloc (2048 * sizeof (int));
+ temp[0] = 1234;
+ memcpy (foobar, temp, 2048 * sizeof (int));
+ free (temp);
+ @endcode
+
+ ..you could just write this:
+ @code
+ HeapBlock <int> temp (1024);
+ memcpy (temp, xyz, 1024 * sizeof (int));
+ temp.calloc (2048);
+ temp[0] = 1234;
+ memcpy (foobar, temp, 2048 * sizeof (int));
+ @endcode
+
+ The class is extremely lightweight, containing only a pointer to the
+ data, and exposes malloc/realloc/calloc/free methods that do the same jobs
+ as their less object-oriented counterparts. Despite adding safety, you probably
+ won't sacrifice any performance by using this in place of normal pointers.
+
+ The throwOnFailure template parameter can be set to true if you'd like the class
+ to throw a std::bad_alloc exception when an allocation fails. If this is false,
+ then a failed allocation will just leave the heapblock with a null pointer (assuming
+ that the system's malloc() function doesn't throw).
+
+ @see Array, OwnedArray, MemoryBlock
+*/
+template <class ElementType, bool throwOnFailure = false>
+class HeapBlock
+{
+public:
+ //==============================================================================
+ /** Creates a HeapBlock which is initially just a null pointer.
+
+ After creation, you can resize the array using the malloc(), calloc(),
+ or realloc() methods.
+ */
+ HeapBlock() noexcept : data (nullptr)
+ {
+ }
+
+ /** Creates a HeapBlock containing a number of elements.
+
+ The contents of the block are undefined, as it will have been created by a
+ malloc call.
+
+ If you want an array of zero values, you can use the calloc() method or the
+ other constructor that takes an InitialisationState parameter.
+ */
+ explicit HeapBlock (const size_t numElements)
+ : data (static_cast <ElementType*> (std::malloc (numElements * sizeof (ElementType))))
+ {
+ throwOnAllocationFailure();
+ }
+
+ /** Creates a HeapBlock containing a number of elements.
+
+ The initialiseToZero parameter determines whether the new memory should be cleared,
+ or left uninitialised.
+ */
+ HeapBlock (const size_t numElements, const bool initialiseToZero)
+ : data (static_cast <ElementType*> (initialiseToZero
+ ? std::calloc (numElements, sizeof (ElementType))
+ : std::malloc (numElements * sizeof (ElementType))))
+ {
+ throwOnAllocationFailure();
+ }
+
+ /** Destructor.
+ This will free the data, if any has been allocated.
+ */
+ ~HeapBlock()
+ {
+ std::free (data);
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ HeapBlock (HeapBlock&& other) noexcept
+ : data (other.data)
+ {
+ other.data = nullptr;
+ }
+
+ HeapBlock& operator= (HeapBlock&& other) noexcept
+ {
+ std::swap (data, other.data);
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Returns a raw pointer to the allocated data.
+ This may be a null pointer if the data hasn't yet been allocated, or if it has been
+ freed by calling the free() method.
+ */
+ inline operator ElementType*() const noexcept { return data; }
+
+ /** Returns a raw pointer to the allocated data.
+ This may be a null pointer if the data hasn't yet been allocated, or if it has been
+ freed by calling the free() method.
+ */
+ inline ElementType* getData() const noexcept { return data; }
+
+ /** Returns a void pointer to the allocated data.
+ This may be a null pointer if the data hasn't yet been allocated, or if it has been
+ freed by calling the free() method.
+ */
+ inline operator void*() const noexcept { return static_cast <void*> (data); }
+
+ /** Returns a void pointer to the allocated data.
+ This may be a null pointer if the data hasn't yet been allocated, or if it has been
+ freed by calling the free() method.
+ */
+ inline operator const void*() const noexcept { return static_cast <const void*> (data); }
+
+ /** Lets you use indirect calls to the first element in the array.
+ Obviously this will cause problems if the array hasn't been initialised, because it'll
+ be referencing a null pointer.
+ */
+ inline ElementType* operator->() const noexcept { return data; }
+
+ /** Returns a reference to one of the data elements.
+ Obviously there's no bounds-checking here, as this object is just a dumb pointer and
+ has no idea of the size it currently has allocated.
+ */
+ template <typename IndexType>
+ inline ElementType& operator[] (IndexType index) const noexcept { return data [index]; }
+
+ /** Returns a pointer to a data element at an offset from the start of the array.
+ This is the same as doing pointer arithmetic on the raw pointer itself.
+ */
+ template <typename IndexType>
+ inline ElementType* operator+ (IndexType index) const noexcept { return data + index; }
+
+ //==============================================================================
+ /** Compares the pointer with another pointer.
+ This can be handy for checking whether this is a null pointer.
+ */
+ inline bool operator== (const ElementType* const otherPointer) const noexcept { return otherPointer == data; }
+
+ /** Compares the pointer with another pointer.
+ This can be handy for checking whether this is a null pointer.
+ */
+ inline bool operator!= (const ElementType* const otherPointer) const noexcept { return otherPointer != data; }
+
+ //==============================================================================
+ /** Allocates a specified amount of memory.
+
+ This uses the normal malloc to allocate an amount of memory for this object.
+ Any previously allocated memory will be freed by this method.
+
+ The number of bytes allocated will be (newNumElements * elementSize). Normally
+ you wouldn't need to specify the second parameter, but it can be handy if you need
+ to allocate a size in bytes rather than in terms of the number of elements.
+
+ The data that is allocated will be freed when this object is deleted, or when you
+ call free() or any of the allocation methods.
+ */
+ void malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
+ {
+ std::free (data);
+ data = static_cast <ElementType*> (std::malloc (newNumElements * elementSize));
+ throwOnAllocationFailure();
+ }
+
+ /** Allocates a specified amount of memory and clears it.
+ This does the same job as the malloc() method, but clears the memory that it allocates.
+ */
+ void calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
+ {
+ std::free (data);
+ data = static_cast <ElementType*> (std::calloc (newNumElements, elementSize));
+ throwOnAllocationFailure();
+ }
+
+ /** Allocates a specified amount of memory and optionally clears it.
+ This does the same job as either malloc() or calloc(), depending on the
+ initialiseToZero parameter.
+ */
+ void allocate (const size_t newNumElements, bool initialiseToZero)
+ {
+ std::free (data);
+ data = static_cast <ElementType*> (initialiseToZero
+ ? std::calloc (newNumElements, sizeof (ElementType))
+ : std::malloc (newNumElements * sizeof (ElementType)));
+ throwOnAllocationFailure();
+ }
+
+ /** Re-allocates a specified amount of memory.
+
+ The semantics of this method are the same as malloc() and calloc(), but it
+ uses realloc() to keep as much of the existing data as possible.
+ */
+ void realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
+ {
+ data = static_cast <ElementType*> (data == nullptr ? std::malloc (newNumElements * elementSize)
+ : std::realloc (data, newNumElements * elementSize));
+ throwOnAllocationFailure();
+ }
+
+ /** Frees any currently-allocated data.
+ This will free the data and reset this object to be a null pointer.
+ */
+ void free()
+ {
+ std::free (data);
+ data = nullptr;
+ }
+
+ /** Swaps this object's data with the data of another HeapBlock.
+ The two objects simply exchange their data pointers.
+ */
+ template <bool otherBlockThrows>
+ void swapWith (HeapBlock <ElementType, otherBlockThrows>& other) noexcept
+ {
+ std::swap (data, other.data);
+ }
+
+ /** This fills the block with zeros, up to the number of elements specified.
+ Since the block has no way of knowing its own size, you must make sure that the number of
+ elements you specify doesn't exceed the allocated size.
+ */
+ void clear (size_t numElements) noexcept
+ {
+ zeromem (data, sizeof (ElementType) * numElements);
+ }
+
+ /** This typedef can be used to get the type of the heapblock's elements. */
+ typedef ElementType Type;
+
+private:
+ //==============================================================================
+ ElementType* data;
+
+ void throwOnAllocationFailure() const
+ {
+ HeapBlockHelper::ThrowOnFail<throwOnFailure>::check (data);
+ }
+
+ #if ! (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD))
+ JUCE_DECLARE_NON_COPYABLE (HeapBlock)
+ JUCE_PREVENT_HEAP_ALLOCATION // Creating a 'new HeapBlock' would be missing the point!
+ #endif
+};
+
+
+#endif // JUCE_HEAPBLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_LeakedObjectDetector.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_LeakedObjectDetector.h
new file mode 100644
index 0000000..248e7bc
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_LeakedObjectDetector.h
@@ -0,0 +1,146 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
+#define JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Embedding an instance of this class inside another class can be used as a low-overhead
+ way of detecting leaked instances.
+
+ This class keeps an internal static count of the number of instances that are
+ active, so that when the app is shutdown and the static destructors are called,
+ it can check whether there are any left-over instances that may have been leaked.
+
+ To use it, use the JUCE_LEAK_DETECTOR macro as a simple way to put one in your
+ class declaration. Have a look through the juce codebase for examples, it's used
+ in most of the classes.
+*/
+template <class OwnerClass>
+class LeakedObjectDetector
+{
+public:
+ //==============================================================================
+ LeakedObjectDetector() noexcept { ++(getCounter().numObjects); }
+ LeakedObjectDetector (const LeakedObjectDetector&) noexcept { ++(getCounter().numObjects); }
+
+ ~LeakedObjectDetector()
+ {
+ if (--(getCounter().numObjects) < 0)
+ {
+ DBG ("*** Dangling pointer deletion! Class: " << getLeakedObjectClassName());
+
+ /** If you hit this, then you've managed to delete more instances of this class than you've
+ created.. That indicates that you're deleting some dangling pointers.
+
+ Note that although this assertion will have been triggered during a destructor, it might
+ not be this particular deletion that's at fault - the incorrect one may have happened
+ at an earlier point in the program, and simply not been detected until now.
+
+ Most errors like this are caused by using old-fashioned, non-RAII techniques for
+ your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
+ ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
+ */
+ jassertfalse;
+ }
+ }
+
+private:
+ //==============================================================================
+ class LeakCounter
+ {
+ public:
+ LeakCounter() noexcept {}
+
+ ~LeakCounter()
+ {
+ if (numObjects.value > 0)
+ {
+ DBG ("*** Leaked objects detected: " << numObjects.value << " instance(s) of class " << getLeakedObjectClassName());
+
+ /** If you hit this, then you've leaked one or more objects of the type specified by
+ the 'OwnerClass' template parameter - the name should have been printed by the line above.
+
+ If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
+ your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
+ ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
+ */
+ jassertfalse;
+ }
+ }
+
+ Atomic<int> numObjects;
+ };
+
+ static const char* getLeakedObjectClassName()
+ {
+ return OwnerClass::getLeakedObjectClassName();
+ }
+
+ static LeakCounter& getCounter() noexcept
+ {
+ static LeakCounter counter;
+ return counter;
+ }
+};
+
+//==============================================================================
+#if DOXYGEN || ! defined (JUCE_LEAK_DETECTOR)
+ #if (DOXYGEN || JUCE_CHECK_MEMORY_LEAKS)
+ /** This macro lets you embed a leak-detecting object inside a class.
+
+ To use it, simply declare a JUCE_LEAK_DETECTOR(YourClassName) inside a private section
+ of the class declaration. E.g.
+
+ @code
+ class MyClass
+ {
+ public:
+ MyClass();
+ void blahBlah();
+
+ private:
+ JUCE_LEAK_DETECTOR (MyClass)
+ };
+ @endcode
+
+ @see JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR, LeakedObjectDetector
+ */
+ #define JUCE_LEAK_DETECTOR(OwnerClass) \
+ friend class juce::LeakedObjectDetector<OwnerClass>; \
+ static const char* getLeakedObjectClassName() noexcept { return #OwnerClass; } \
+ juce::LeakedObjectDetector<OwnerClass> JUCE_JOIN_MACRO (leakDetector, __LINE__);
+ #else
+ #define JUCE_LEAK_DETECTOR(OwnerClass)
+ #endif
+#endif
+
+
+#endif // JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Memory.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Memory.h
new file mode 100644
index 0000000..57d1644
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Memory.h
@@ -0,0 +1,126 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MEMORY_H_INCLUDED
+#define JUCE_MEMORY_H_INCLUDED
+
+//==============================================================================
+/** Fills a block of memory with zeros. */
+inline void zeromem (void* memory, size_t numBytes) noexcept { memset (memory, 0, numBytes); }
+
+/** Overwrites a structure or object with zeros. */
+template <typename Type>
+inline void zerostruct (Type& structure) noexcept { memset (&structure, 0, sizeof (structure)); }
+
+/** Delete an object pointer, and sets the pointer to null.
+
+ Remember that it's not good c++ practice to use delete directly - always try to use a ScopedPointer
+ or other automatic lifetime-management system rather than resorting to deleting raw pointers!
+*/
+template <typename Type>
+inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; }
+
+/** A handy function which adds a number of bytes to any type of pointer and returns the result.
+ This can be useful to avoid casting pointers to a char* and back when you want to move them by
+ a specific number of bytes,
+*/
+template <typename Type, typename IntegerType>
+inline Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept { return (Type*) (((char*) pointer) + bytes); }
+
+/** A handy function which returns the difference between any two pointers, in bytes.
+ The address of the second pointer is subtracted from the first, and the difference in bytes is returned.
+*/
+template <typename Type1, typename Type2>
+inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { return (int) (((const char*) pointer1) - (const char*) pointer2); }
+
+/** If a pointer is non-null, this returns a new copy of the object that it points to, or safely returns
+ nullptr if the pointer is null.
+*/
+template <class Type>
+inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != nullptr ? new Type (*pointer) : nullptr; }
+
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS || DOXYGEN
+
+ /** A handy C++ wrapper that creates and deletes an NSAutoreleasePool object using RAII.
+ You should use the JUCE_AUTORELEASEPOOL macro to create a local auto-release pool on the stack.
+ */
+ class JUCE_API ScopedAutoReleasePool
+ {
+ public:
+ ScopedAutoReleasePool();
+ ~ScopedAutoReleasePool();
+
+ private:
+ void* pool;
+
+ JUCE_DECLARE_NON_COPYABLE (ScopedAutoReleasePool)
+ };
+
+ /** A macro that can be used to easily declare a local ScopedAutoReleasePool
+ object for RAII-based obj-C autoreleasing.
+ Because this may use the \@autoreleasepool syntax, you must follow the macro with
+ a set of braces to mark the scope of the pool.
+ */
+#if (JUCE_COMPILER_SUPPORTS_ARC && defined (__OBJC__)) || DOXYGEN
+ #define JUCE_AUTORELEASEPOOL @autoreleasepool
+#else
+ #define JUCE_AUTORELEASEPOOL const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__);
+#endif
+
+#else
+ #define JUCE_AUTORELEASEPOOL
+#endif
+
+//==============================================================================
+/* In a Windows DLL build, we'll expose some malloc/free functions that live inside the DLL, and use these for
+ allocating all the objects - that way all juce objects in the DLL and in the host will live in the same heap,
+ avoiding problems when an object is created in one module and passed across to another where it is deleted.
+ By piggy-backing on the JUCE_LEAK_DETECTOR macro, these allocators can be injected into most juce classes.
+*/
+#if JUCE_MSVC && (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD)) && ! (JUCE_DISABLE_DLL_ALLOCATORS || DOXYGEN)
+ extern JUCE_API void* juceDLL_malloc (size_t);
+ extern JUCE_API void juceDLL_free (void*);
+
+ #define JUCE_LEAK_DETECTOR(OwnerClass) public:\
+ static void* operator new (size_t sz) { return juce::juceDLL_malloc (sz); } \
+ static void* operator new (size_t, void* p) { return p; } \
+ static void operator delete (void* p) { juce::juceDLL_free (p); } \
+ static void operator delete (void*, void*) {}
+#endif
+
+//==============================================================================
+/** (Deprecated) This was a Windows-specific way of checking for object leaks - now please
+ use the JUCE_LEAK_DETECTOR instead.
+*/
+#ifndef juce_UseDebuggingNewOperator
+ #define juce_UseDebuggingNewOperator
+#endif
+
+
+#endif // JUCE_MEMORY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.cpp
new file mode 100644
index 0000000..a827037
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.cpp
@@ -0,0 +1,416 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+MemoryBlock::MemoryBlock() noexcept
+ : size (0)
+{
+}
+
+MemoryBlock::MemoryBlock (const size_t initialSize, const bool initialiseToZero)
+{
+ if (initialSize > 0)
+ {
+ size = initialSize;
+ data.allocate (initialSize, initialiseToZero);
+ }
+ else
+ {
+ size = 0;
+ }
+}
+
+MemoryBlock::MemoryBlock (const MemoryBlock& other)
+ : size (other.size)
+{
+ if (size > 0)
+ {
+ jassert (other.data != nullptr);
+ data.malloc (size);
+ memcpy (data, other.data, size);
+ }
+}
+
+MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, const size_t sizeInBytes)
+ : size (sizeInBytes)
+{
+ jassert (((ssize_t) sizeInBytes) >= 0);
+
+ if (size > 0)
+ {
+ jassert (dataToInitialiseFrom != nullptr); // non-zero size, but a zero pointer passed-in?
+
+ data.malloc (size);
+
+ if (dataToInitialiseFrom != nullptr)
+ memcpy (data, dataToInitialiseFrom, size);
+ }
+}
+
+MemoryBlock::~MemoryBlock() noexcept
+{
+}
+
+MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other)
+{
+ if (this != &other)
+ {
+ setSize (other.size, false);
+ memcpy (data, other.data, size);
+ }
+
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+MemoryBlock::MemoryBlock (MemoryBlock&& other) noexcept
+ : data (static_cast <HeapBlock<char>&&> (other.data)),
+ size (other.size)
+{
+}
+
+MemoryBlock& MemoryBlock::operator= (MemoryBlock&& other) noexcept
+{
+ data = static_cast <HeapBlock<char>&&> (other.data);
+ size = other.size;
+ return *this;
+}
+#endif
+
+
+//==============================================================================
+bool MemoryBlock::operator== (const MemoryBlock& other) const noexcept
+{
+ return matches (other.data, other.size);
+}
+
+bool MemoryBlock::operator!= (const MemoryBlock& other) const noexcept
+{
+ return ! operator== (other);
+}
+
+bool MemoryBlock::matches (const void* dataToCompare, size_t dataSize) const noexcept
+{
+ return size == dataSize
+ && memcmp (data, dataToCompare, size) == 0;
+}
+
+//==============================================================================
+// this will resize the block to this size
+void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
+{
+ if (size != newSize)
+ {
+ if (newSize <= 0)
+ {
+ reset();
+ }
+ else
+ {
+ if (data != nullptr)
+ {
+ data.realloc (newSize);
+
+ if (initialiseToZero && (newSize > size))
+ zeromem (data + size, newSize - size);
+ }
+ else
+ {
+ data.allocate (newSize, initialiseToZero);
+ }
+
+ size = newSize;
+ }
+ }
+}
+
+void MemoryBlock::reset()
+{
+ data.free();
+ size = 0;
+}
+
+void MemoryBlock::ensureSize (const size_t minimumSize, const bool initialiseToZero)
+{
+ if (size < minimumSize)
+ setSize (minimumSize, initialiseToZero);
+}
+
+void MemoryBlock::swapWith (MemoryBlock& other) noexcept
+{
+ std::swap (size, other.size);
+ data.swapWith (other.data);
+}
+
+//==============================================================================
+void MemoryBlock::fillWith (const uint8 value) noexcept
+{
+ memset (data, (int) value, size);
+}
+
+void MemoryBlock::append (const void* const srcData, const size_t numBytes)
+{
+ if (numBytes > 0)
+ {
+ jassert (srcData != nullptr); // this must not be null!
+ const size_t oldSize = size;
+ setSize (size + numBytes);
+ memcpy (data + oldSize, srcData, numBytes);
+ }
+}
+
+void MemoryBlock::replaceWith (const void* const srcData, const size_t numBytes)
+{
+ if (numBytes > 0)
+ {
+ jassert (srcData != nullptr); // this must not be null!
+ setSize (numBytes);
+ memcpy (data, srcData, numBytes);
+ }
+}
+
+void MemoryBlock::insert (const void* const srcData, const size_t numBytes, size_t insertPosition)
+{
+ if (numBytes > 0)
+ {
+ jassert (srcData != nullptr); // this must not be null!
+ insertPosition = jmin (size, insertPosition);
+ const size_t trailingDataSize = size - insertPosition;
+ setSize (size + numBytes, false);
+
+ if (trailingDataSize > 0)
+ memmove (data + insertPosition + numBytes,
+ data + insertPosition,
+ trailingDataSize);
+
+ memcpy (data + insertPosition, srcData, numBytes);
+ }
+}
+
+void MemoryBlock::removeSection (const size_t startByte, const size_t numBytesToRemove)
+{
+ if (startByte + numBytesToRemove >= size)
+ {
+ setSize (startByte);
+ }
+ else if (numBytesToRemove > 0)
+ {
+ memmove (data + startByte,
+ data + startByte + numBytesToRemove,
+ size - (startByte + numBytesToRemove));
+
+ setSize (size - numBytesToRemove);
+ }
+}
+
+void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
+{
+ const char* d = static_cast<const char*> (src);
+
+ if (offset < 0)
+ {
+ d -= offset;
+ num += (size_t) -offset;
+ offset = 0;
+ }
+
+ if ((size_t) offset + num > size)
+ num = size - (size_t) offset;
+
+ if (num > 0)
+ memcpy (data + offset, d, num);
+}
+
+void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
+{
+ char* d = static_cast<char*> (dst);
+
+ if (offset < 0)
+ {
+ zeromem (d, (size_t) -offset);
+ d -= offset;
+ num -= (size_t) -offset;
+ offset = 0;
+ }
+
+ if ((size_t) offset + num > size)
+ {
+ const size_t newNum = size - (size_t) offset;
+ zeromem (d + newNum, num - newNum);
+ num = newNum;
+ }
+
+ if (num > 0)
+ memcpy (d, data + offset, num);
+}
+
+String MemoryBlock::toString() const
+{
+ return String::fromUTF8 (data, (int) size);
+}
+
+//==============================================================================
+int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const noexcept
+{
+ int res = 0;
+
+ size_t byte = bitRangeStart >> 3;
+ size_t offsetInByte = bitRangeStart & 7;
+ size_t bitsSoFar = 0;
+
+ while (numBits > 0 && (size_t) byte < size)
+ {
+ const size_t bitsThisTime = jmin (numBits, 8 - offsetInByte);
+ const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
+
+ res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
+
+ bitsSoFar += bitsThisTime;
+ numBits -= bitsThisTime;
+ ++byte;
+ offsetInByte = 0;
+ }
+
+ return res;
+}
+
+void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
+{
+ size_t byte = bitRangeStart >> 3;
+ size_t offsetInByte = bitRangeStart & 7;
+ uint32 mask = ~((((uint32) 0xffffffff) << (32 - numBits)) >> (32 - numBits));
+
+ while (numBits > 0 && (size_t) byte < size)
+ {
+ const size_t bitsThisTime = jmin (numBits, 8 - offsetInByte);
+
+ const uint32 tempMask = (mask << offsetInByte) | ~((((uint32) 0xffffffff) >> offsetInByte) << offsetInByte);
+ const uint32 tempBits = (uint32) bitsToSet << offsetInByte;
+
+ data[byte] = (char) (((uint32) data[byte] & tempMask) | tempBits);
+
+ ++byte;
+ numBits -= bitsThisTime;
+ bitsToSet >>= bitsThisTime;
+ mask >>= bitsThisTime;
+ offsetInByte = 0;
+ }
+}
+
+//==============================================================================
+void MemoryBlock::loadFromHexString (StringRef hex)
+{
+ ensureSize ((size_t) hex.length() >> 1);
+ char* dest = data;
+ String::CharPointerType t (hex.text);
+
+ for (;;)
+ {
+ int byte = 0;
+
+ for (int loop = 2; --loop >= 0;)
+ {
+ byte <<= 4;
+
+ for (;;)
+ {
+ const juce_wchar c = t.getAndAdvance();
+
+ if (c >= '0' && c <= '9') { byte |= c - '0'; break; }
+ if (c >= 'a' && c <= 'z') { byte |= c - ('a' - 10); break; }
+ if (c >= 'A' && c <= 'Z') { byte |= c - ('A' - 10); break; }
+
+ if (c == 0)
+ {
+ setSize (static_cast <size_t> (dest - data));
+ return;
+ }
+ }
+ }
+
+ *dest++ = (char) byte;
+ }
+}
+
+//==============================================================================
+static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
+
+String MemoryBlock::toBase64Encoding() const
+{
+ const size_t numChars = ((size << 3) + 5) / 6;
+
+ String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
+ const int initialLen = destString.length();
+ destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (size_t) initialLen + 2 + numChars);
+
+ String::CharPointerType d (destString.getCharPointer());
+ d += initialLen;
+ d.write ('.');
+
+ for (size_t i = 0; i < numChars; ++i)
+ d.write ((juce_wchar) (uint8) base64EncodingTable [getBitRange (i * 6, 6)]);
+
+ d.writeNull();
+ return destString;
+}
+
+static const char base64DecodingTable[] =
+{
+ 63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52
+};
+
+bool MemoryBlock::fromBase64Encoding (StringRef s)
+{
+ String::CharPointerType dot (CharacterFunctions::find (s.text, (juce_wchar) '.'));
+
+ if (dot.isEmpty())
+ return false;
+
+ const int numBytesNeeded = String (s.text, dot).getIntValue();
+
+ setSize ((size_t) numBytesNeeded, true);
+
+ String::CharPointerType srcChars (dot + 1);
+ int pos = 0;
+
+ for (;;)
+ {
+ int c = (int) srcChars.getAndAdvance();
+
+ if (c == 0)
+ return true;
+
+ c -= 43;
+ if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
+ {
+ setBitRange ((size_t) pos, 6, base64DecodingTable [c]);
+ pos += 6;
+ }
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.h
new file mode 100644
index 0000000..30bb3ca
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_MemoryBlock.h
@@ -0,0 +1,253 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MEMORYBLOCK_H_INCLUDED
+#define JUCE_MEMORYBLOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A class to hold a resizable block of raw data.
+
+*/
+class JUCE_API MemoryBlock
+{
+public:
+ //==============================================================================
+ /** Create an uninitialised block with 0 size. */
+ MemoryBlock() noexcept;
+
+ /** Creates a memory block with a given initial size.
+
+ @param initialSize the size of block to create
+ @param initialiseToZero whether to clear the memory or just leave it uninitialised
+ */
+ MemoryBlock (const size_t initialSize,
+ bool initialiseToZero = false);
+
+ /** Creates a copy of another memory block. */
+ MemoryBlock (const MemoryBlock&);
+
+ /** Creates a memory block using a copy of a block of data.
+
+ @param dataToInitialiseFrom some data to copy into this block
+ @param sizeInBytes how much space to use
+ */
+ MemoryBlock (const void* dataToInitialiseFrom, size_t sizeInBytes);
+
+ /** Destructor. */
+ ~MemoryBlock() noexcept;
+
+ /** Copies another memory block onto this one.
+ This block will be resized and copied to exactly match the other one.
+ */
+ MemoryBlock& operator= (const MemoryBlock&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ MemoryBlock (MemoryBlock&&) noexcept;
+ MemoryBlock& operator= (MemoryBlock&&) noexcept;
+ #endif
+
+ //==============================================================================
+ /** Compares two memory blocks.
+ @returns true only if the two blocks are the same size and have identical contents.
+ */
+ bool operator== (const MemoryBlock& other) const noexcept;
+
+ /** Compares two memory blocks.
+ @returns true if the two blocks are different sizes or have different contents.
+ */
+ bool operator!= (const MemoryBlock& other) const noexcept;
+
+ /** Returns true if the data in this MemoryBlock matches the raw bytes passed-in. */
+ bool matches (const void* data, size_t dataSize) const noexcept;
+
+ //==============================================================================
+ /** Returns a void pointer to the data.
+
+ Note that the pointer returned will probably become invalid when the
+ block is resized.
+ */
+ void* getData() const noexcept { return data; }
+
+ /** Returns a byte from the memory block.
+ This returns a reference, so you can also use it to set a byte.
+ */
+ template <typename Type>
+ char& operator[] (const Type offset) const noexcept { return data [offset]; }
+
+
+ //==============================================================================
+ /** Returns the block's current allocated size, in bytes. */
+ size_t getSize() const noexcept { return size; }
+
+ /** Resizes the memory block.
+
+ Any data that is present in both the old and new sizes will be retained.
+ When enlarging the block, the new space that is allocated at the end can either be
+ cleared, or left uninitialised.
+
+ @param newSize the new desired size for the block
+ @param initialiseNewSpaceToZero if the block gets enlarged, this determines
+ whether to clear the new section or just leave it
+ uninitialised
+ @see ensureSize
+ */
+ void setSize (const size_t newSize,
+ bool initialiseNewSpaceToZero = false);
+
+ /** Increases the block's size only if it's smaller than a given size.
+
+ @param minimumSize if the block is already bigger than this size, no action
+ will be taken; otherwise it will be increased to this size
+ @param initialiseNewSpaceToZero if the block gets enlarged, this determines
+ whether to clear the new section or just leave it
+ uninitialised
+ @see setSize
+ */
+ void ensureSize (const size_t minimumSize,
+ bool initialiseNewSpaceToZero = false);
+
+ /** Frees all the blocks data, setting its size to 0. */
+ void reset();
+
+ //==============================================================================
+ /** Fills the entire memory block with a repeated byte value.
+ This is handy for clearing a block of memory to zero.
+ */
+ void fillWith (uint8 valueToUse) noexcept;
+
+ /** Adds another block of data to the end of this one.
+ The data pointer must not be null. This block's size will be increased accordingly.
+ */
+ void append (const void* data, size_t numBytes);
+
+ /** Resizes this block to the given size and fills its contents from the supplied buffer.
+ The data pointer must not be null.
+ */
+ void replaceWith (const void* data, size_t numBytes);
+
+ /** Inserts some data into the block.
+ The dataToInsert pointer must not be null. This block's size will be increased accordingly.
+ If the insert position lies outside the valid range of the block, it will be clipped to
+ within the range before being used.
+ */
+ void insert (const void* dataToInsert, size_t numBytesToInsert, size_t insertPosition);
+
+ /** Chops out a section of the block.
+
+ This will remove a section of the memory block and close the gap around it,
+ shifting any subsequent data downwards and reducing the size of the block.
+
+ If the range specified goes beyond the size of the block, it will be clipped.
+ */
+ void removeSection (size_t startByte, size_t numBytesToRemove);
+
+ //==============================================================================
+ /** Copies data into this MemoryBlock from a memory address.
+
+ @param srcData the memory location of the data to copy into this block
+ @param destinationOffset the offset in this block at which the data being copied should begin
+ @param numBytes how much to copy in (if this goes beyond the size of the memory block,
+ it will be clipped so not to do anything nasty)
+ */
+ void copyFrom (const void* srcData,
+ int destinationOffset,
+ size_t numBytes) noexcept;
+
+ /** Copies data from this MemoryBlock to a memory address.
+
+ @param destData the memory location to write to
+ @param sourceOffset the offset within this block from which the copied data will be read
+ @param numBytes how much to copy (if this extends beyond the limits of the memory block,
+ zeros will be used for that portion of the data)
+ */
+ void copyTo (void* destData,
+ int sourceOffset,
+ size_t numBytes) const noexcept;
+
+ //==============================================================================
+ /** Exchanges the contents of this and another memory block.
+ No actual copying is required for this, so it's very fast.
+ */
+ void swapWith (MemoryBlock& other) noexcept;
+
+ //==============================================================================
+ /** Attempts to parse the contents of the block as a zero-terminated UTF8 string. */
+ String toString() const;
+
+ //==============================================================================
+ /** Parses a string of hexadecimal numbers and writes this data into the memory block.
+
+ The block will be resized to the number of valid bytes read from the string.
+ Non-hex characters in the string will be ignored.
+
+ @see String::toHexString()
+ */
+ void loadFromHexString (StringRef sourceHexString);
+
+ //==============================================================================
+ /** Sets a number of bits in the memory block, treating it as a long binary sequence. */
+ void setBitRange (size_t bitRangeStart,
+ size_t numBits,
+ int binaryNumberToApply) noexcept;
+
+ /** Reads a number of bits from the memory block, treating it as one long binary sequence */
+ int getBitRange (size_t bitRangeStart,
+ size_t numBitsToRead) const noexcept;
+
+ //==============================================================================
+ /** Returns a string of characters that represent the binary contents of this block.
+
+ Uses a 64-bit encoding system to allow binary data to be turned into a string
+ of simple non-extended characters, e.g. for storage in XML.
+
+ @see fromBase64Encoding
+ */
+ String toBase64Encoding() const;
+
+ /** Takes a string of encoded characters and turns it into binary data.
+
+ The string passed in must have been created by to64BitEncoding(), and this
+ block will be resized to recreate the original data block.
+
+ @see toBase64Encoding
+ */
+ bool fromBase64Encoding (StringRef encodedString);
+
+
+private:
+ //==============================================================================
+ HeapBlock<char> data;
+ size_t size;
+
+ JUCE_LEAK_DETECTOR (MemoryBlock)
+};
+
+
+#endif // JUCE_MEMORYBLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_OptionalScopedPointer.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_OptionalScopedPointer.h
new file mode 100644
index 0000000..a633dca
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_OptionalScopedPointer.h
@@ -0,0 +1,186 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
+#define JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Holds a pointer to an object which can optionally be deleted when this pointer
+ goes out of scope.
+
+ This acts in many ways like a ScopedPointer, but allows you to specify whether or
+ not the object is deleted.
+
+ @see ScopedPointer
+*/
+template <class ObjectType>
+class OptionalScopedPointer
+{
+public:
+ //==============================================================================
+ /** Creates an empty OptionalScopedPointer. */
+ OptionalScopedPointer() : shouldDelete (false) {}
+
+ /** Creates an OptionalScopedPointer to point to a given object, and specifying whether
+ the OptionalScopedPointer will delete it.
+
+ If takeOwnership is true, then the OptionalScopedPointer will act like a ScopedPointer,
+ deleting the object when it is itself deleted. If this parameter is false, then the
+ OptionalScopedPointer just holds a normal pointer to the object, and won't delete it.
+ */
+ OptionalScopedPointer (ObjectType* objectToHold, bool takeOwnership)
+ : object (objectToHold), shouldDelete (takeOwnership)
+ {
+ }
+
+ /** Takes ownership of the object that another OptionalScopedPointer holds.
+
+ Like a normal ScopedPointer, the objectToTransferFrom object will become null,
+ as ownership of the managed object is transferred to this object.
+
+ The flag to indicate whether or not to delete the managed object is also
+ copied from the source object.
+ */
+ OptionalScopedPointer (OptionalScopedPointer& objectToTransferFrom)
+ : object (objectToTransferFrom.release()),
+ shouldDelete (objectToTransferFrom.shouldDelete)
+ {
+ }
+
+ /** Takes ownership of the object that another OptionalScopedPointer holds.
+
+ Like a normal ScopedPointer, the objectToTransferFrom object will become null,
+ as ownership of the managed object is transferred to this object.
+
+ The ownership flag that says whether or not to delete the managed object is also
+ copied from the source object.
+ */
+ OptionalScopedPointer& operator= (OptionalScopedPointer& objectToTransferFrom)
+ {
+ if (object != objectToTransferFrom.object)
+ {
+ clear();
+ object = objectToTransferFrom.object;
+ }
+
+ shouldDelete = objectToTransferFrom.shouldDelete;
+ return *this;
+ }
+
+ /** The destructor may or may not delete the object that is being held, depending on the
+ takeOwnership flag that was specified when the object was first passed into an
+ OptionalScopedPointer constructor.
+ */
+ ~OptionalScopedPointer()
+ {
+ clear();
+ }
+
+ //==============================================================================
+ /** Returns the object that this pointer is managing. */
+ inline operator ObjectType*() const noexcept { return object; }
+
+ /** Returns the object that this pointer is managing. */
+ inline ObjectType* get() const noexcept { return object; }
+
+ /** Returns the object that this pointer is managing. */
+ inline ObjectType& operator*() const noexcept { return *object; }
+
+ /** Lets you access methods and properties of the object that this pointer is holding. */
+ inline ObjectType* operator->() const noexcept { return object; }
+
+ //==============================================================================
+ /** Removes the current object from this OptionalScopedPointer without deleting it.
+ This will return the current object, and set this OptionalScopedPointer to a null pointer.
+ */
+ ObjectType* release() noexcept { return object.release(); }
+
+ /** Resets this pointer to null, possibly deleting the object that it holds, if it has
+ ownership of it.
+ */
+ void clear()
+ {
+ if (! shouldDelete)
+ object.release();
+ }
+
+ /** Makes this OptionalScopedPointer point at a new object, specifying whether the
+ OptionalScopedPointer will take ownership of the object.
+
+ If takeOwnership is true, then the OptionalScopedPointer will act like a ScopedPointer,
+ deleting the object when it is itself deleted. If this parameter is false, then the
+ OptionalScopedPointer just holds a normal pointer to the object, and won't delete it.
+ */
+ void set (ObjectType* newObject, bool takeOwnership)
+ {
+ if (object != newObject)
+ {
+ clear();
+ object = newObject;
+ }
+
+ shouldDelete = takeOwnership;
+ }
+
+ /** Makes this OptionalScopedPointer point at a new object, and take ownership of that object. */
+ void setOwned (ObjectType* newObject)
+ {
+ set (newObject, true);
+ }
+
+ /** Makes this OptionalScopedPointer point at a new object, but will not take ownership of that object. */
+ void setNonOwned (ObjectType* newObject)
+ {
+ set (newObject, false);
+ }
+
+ /** Returns true if the target object will be deleted when this pointer
+ object is deleted.
+ */
+ bool willDeleteObject() const noexcept { return shouldDelete; }
+
+ //==============================================================================
+ /** Swaps this object with another OptionalScopedPointer.
+ The two objects simply exchange their states.
+ */
+ void swapWith (OptionalScopedPointer<ObjectType>& other) noexcept
+ {
+ object.swapWith (other.object);
+ std::swap (shouldDelete, other.shouldDelete);
+ }
+
+private:
+ //==============================================================================
+ ScopedPointer<ObjectType> object;
+ bool shouldDelete;
+};
+
+
+#endif // JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ReferenceCountedObject.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ReferenceCountedObject.h
new file mode 100644
index 0000000..6464d85
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ReferenceCountedObject.h
@@ -0,0 +1,415 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
+#define JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A base class which provides methods for reference-counting.
+
+ To add reference-counting to a class, derive it from this class, and
+ use the ReferenceCountedObjectPtr class to point to it.
+
+ e.g. @code
+ class MyClass : public ReferenceCountedObject
+ {
+ void foo();
+
+ // This is a neat way of declaring a typedef for a pointer class,
+ // rather than typing out the full templated name each time..
+ typedef ReferenceCountedObjectPtr<MyClass> Ptr;
+ };
+
+ MyClass::Ptr p = new MyClass();
+ MyClass::Ptr p2 = p;
+ p = nullptr;
+ p2->foo();
+ @endcode
+
+ Once a new ReferenceCountedObject has been assigned to a pointer, be
+ careful not to delete the object manually.
+
+ This class uses an Atomic<int> value to hold the reference count, so that it
+ the pointers can be passed between threads safely. For a faster but non-thread-safe
+ version, use SingleThreadedReferenceCountedObject instead.
+
+ @see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject
+*/
+class JUCE_API ReferenceCountedObject
+{
+public:
+ //==============================================================================
+ /** Increments the object's reference count.
+
+ This is done automatically by the smart pointer, but is public just
+ in case it's needed for nefarious purposes.
+ */
+ void incReferenceCount() noexcept
+ {
+ ++refCount;
+ }
+
+ /** Decreases the object's reference count.
+ If the count gets to zero, the object will be deleted.
+ */
+ void decReferenceCount() noexcept
+ {
+ jassert (getReferenceCount() > 0);
+
+ if (--refCount == 0)
+ delete this;
+ }
+
+ /** Decreases the object's reference count.
+ If the count gets to zero, the object will not be deleted, but this method
+ will return true, allowing the caller to take care of deletion.
+ */
+ bool decReferenceCountWithoutDeleting() noexcept
+ {
+ jassert (getReferenceCount() > 0);
+ return --refCount == 0;
+ }
+
+ /** Returns the object's current reference count. */
+ int getReferenceCount() const noexcept { return refCount.get(); }
+
+
+protected:
+ //==============================================================================
+ /** Creates the reference-counted object (with an initial ref count of zero). */
+ ReferenceCountedObject() {}
+
+ /** Destructor. */
+ virtual ~ReferenceCountedObject()
+ {
+ // it's dangerous to delete an object that's still referenced by something else!
+ jassert (getReferenceCount() == 0);
+ }
+
+ /** Resets the reference count to zero without deleting the object.
+ You should probably never need to use this!
+ */
+ void resetReferenceCount() noexcept
+ {
+ refCount = 0;
+ }
+
+private:
+ //==============================================================================
+ Atomic <int> refCount;
+
+ friend struct ContainerDeletePolicy<ReferenceCountedObject>;
+ JUCE_DECLARE_NON_COPYABLE (ReferenceCountedObject)
+};
+
+
+//==============================================================================
+/**
+ Adds reference-counting to an object.
+
+ This is effectively a version of the ReferenceCountedObject class, but which
+ uses a non-atomic counter, and so is not thread-safe (but which will be more
+ efficient).
+ For more details on how to use it, see the ReferenceCountedObject class notes.
+
+ @see ReferenceCountedObject, ReferenceCountedObjectPtr, ReferenceCountedArray
+*/
+class JUCE_API SingleThreadedReferenceCountedObject
+{
+public:
+ //==============================================================================
+ /** Increments the object's reference count.
+
+ This is done automatically by the smart pointer, but is public just
+ in case it's needed for nefarious purposes.
+ */
+ void incReferenceCount() noexcept
+ {
+ ++refCount;
+ }
+
+ /** Decreases the object's reference count.
+ If the count gets to zero, the object will be deleted.
+ */
+ void decReferenceCount() noexcept
+ {
+ jassert (getReferenceCount() > 0);
+
+ if (--refCount == 0)
+ delete this;
+ }
+
+ /** Decreases the object's reference count.
+ If the count gets to zero, the object will not be deleted, but this method
+ will return true, allowing the caller to take care of deletion.
+ */
+ bool decReferenceCountWithoutDeleting() noexcept
+ {
+ jassert (getReferenceCount() > 0);
+ return --refCount == 0;
+ }
+
+ /** Returns the object's current reference count. */
+ int getReferenceCount() const noexcept { return refCount; }
+
+
+protected:
+ //==============================================================================
+ /** Creates the reference-counted object (with an initial ref count of zero). */
+ SingleThreadedReferenceCountedObject() : refCount (0) {}
+
+ /** Destructor. */
+ virtual ~SingleThreadedReferenceCountedObject()
+ {
+ // it's dangerous to delete an object that's still referenced by something else!
+ jassert (getReferenceCount() == 0);
+ }
+
+private:
+ //==============================================================================
+ int refCount;
+
+ friend struct ContainerDeletePolicy<ReferenceCountedObject>;
+ JUCE_DECLARE_NON_COPYABLE (SingleThreadedReferenceCountedObject)
+};
+
+
+//==============================================================================
+/**
+ A smart-pointer class which points to a reference-counted object.
+
+ The template parameter specifies the class of the object you want to point to - the easiest
+ way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject
+ or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable
+ class by implementing a set of mathods called incReferenceCount(), decReferenceCount(), and
+ decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods
+ should behave.
+
+ When using this class, you'll probably want to create a typedef to abbreviate the full
+ templated name - e.g.
+ @code
+ struct MyClass : public ReferenceCountedObject
+ {
+ typedef ReferenceCountedObjectPtr<MyClass> Ptr;
+ ...
+ @endcode
+
+ @see ReferenceCountedObject, ReferenceCountedObjectArray
+*/
+template <class ReferenceCountedObjectClass>
+class ReferenceCountedObjectPtr
+{
+public:
+ /** The class being referenced by this pointer. */
+ typedef ReferenceCountedObjectClass ReferencedType;
+
+ //==============================================================================
+ /** Creates a pointer to a null object. */
+ ReferenceCountedObjectPtr() noexcept
+ : referencedObject (nullptr)
+ {
+ }
+
+ /** Creates a pointer to an object.
+ This will increment the object's reference-count.
+ */
+ ReferenceCountedObjectPtr (ReferencedType* refCountedObject) noexcept
+ : referencedObject (refCountedObject)
+ {
+ incIfNotNull (refCountedObject);
+ }
+
+ /** Copies another pointer.
+ This will increment the object's reference-count.
+ */
+ ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr& other) noexcept
+ : referencedObject (other.referencedObject)
+ {
+ incIfNotNull (referencedObject);
+ }
+
+ /** Copies another pointer.
+ This will increment the object's reference-count (if it is non-null).
+ */
+ template <class Convertible>
+ ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr<Convertible>& other) noexcept
+ : referencedObject (static_cast <ReferencedType*> (other.get()))
+ {
+ incIfNotNull (referencedObject);
+ }
+
+ /** Changes this pointer to point at a different object.
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr& other)
+ {
+ return operator= (other.referencedObject);
+ }
+
+ /** Changes this pointer to point at a different object.
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ template <class Convertible>
+ ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr<Convertible>& other)
+ {
+ return operator= (static_cast<ReferencedType*> (other.get()));
+ }
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ ReferenceCountedObjectPtr& operator= (ReferencedType* const newObject)
+ {
+ if (referencedObject != newObject)
+ {
+ incIfNotNull (newObject);
+ ReferencedType* const oldObject = referencedObject;
+ referencedObject = newObject;
+ decIfNotNull (oldObject);
+ }
+
+ return *this;
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Takes-over the object from another pointer. */
+ ReferenceCountedObjectPtr (ReferenceCountedObjectPtr&& other) noexcept
+ : referencedObject (other.referencedObject)
+ {
+ other.referencedObject = nullptr;
+ }
+
+ /** Takes-over the object from another pointer. */
+ ReferenceCountedObjectPtr& operator= (ReferenceCountedObjectPtr&& other)
+ {
+ std::swap (referencedObject, other.referencedObject);
+ return *this;
+ }
+ #endif
+
+ /** Destructor.
+ This will decrement the object's reference-count, which will cause the
+ object to be deleted when the ref-count hits zero.
+ */
+ ~ReferenceCountedObjectPtr()
+ {
+ decIfNotNull (referencedObject);
+ }
+
+ //==============================================================================
+ /** Returns the object that this pointer references.
+ The pointer returned may be null, of course.
+ */
+ operator ReferencedType*() const noexcept { return referencedObject; }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be null, of course.
+ */
+ ReferencedType* get() const noexcept { return referencedObject; }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be null, of course.
+ */
+ ReferencedType* getObject() const noexcept { return referencedObject; }
+
+ // the -> operator is called on the referenced object
+ ReferencedType* operator->() const noexcept
+ {
+ jassert (referencedObject != nullptr); // null pointer method call!
+ return referencedObject;
+ }
+
+private:
+ //==============================================================================
+ ReferencedType* referencedObject;
+
+ static void incIfNotNull (ReferencedType* o) noexcept
+ {
+ if (o != nullptr)
+ o->incReferenceCount();
+ }
+
+ static void decIfNotNull (ReferencedType* o) noexcept
+ {
+ if (o != nullptr && o->decReferenceCountWithoutDeleting())
+ ContainerDeletePolicy<ReferencedType>::destroy (o);
+ }
+};
+
+
+//==============================================================================
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2) noexcept
+{
+ return object1.get() == object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
+{
+ return object1.get() == object2.get();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (ReferenceCountedObjectClass* object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
+{
+ return object1 == object2.get();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2) noexcept
+{
+ return object1.get() != object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
+{
+ return object1.get() != object2.get();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (ReferenceCountedObjectClass* object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
+{
+ return object1 != object2.get();
+}
+
+
+#endif // JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ScopedPointer.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ScopedPointer.h
new file mode 100644
index 0000000..a7fcff0
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_ScopedPointer.h
@@ -0,0 +1,253 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SCOPEDPOINTER_H_INCLUDED
+#define JUCE_SCOPEDPOINTER_H_INCLUDED
+
+//==============================================================================
+/**
+ This class holds a pointer which is automatically deleted when this object goes
+ out of scope.
+
+ Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
+ gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
+ as member variables is a good way to use RAII to avoid accidentally leaking dynamically
+ created objects.
+
+ A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
+ to an object. If you use the assignment operator to assign a different object to a
+ ScopedPointer, the old one will be automatically deleted.
+
+ Important note: The class is designed to hold a pointer to an object, NOT to an array!
+ It calls delete on its payload, not delete[], so do not give it an array to hold! For
+ that kind of purpose, you should be using HeapBlock or Array instead.
+
+ A const ScopedPointer is guaranteed not to lose ownership of its object or change the
+ object to which it points during its lifetime. This means that making a copy of a const
+ ScopedPointer is impossible, as that would involve the new copy taking ownership from the
+ old one.
+
+ If you need to get a pointer out of a ScopedPointer without it being deleted, you
+ can use the release() method.
+
+ Something to note is the main difference between this class and the std::auto_ptr class,
+ which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr
+ requires that you always call get() to retrieve the pointer. The advantages of providing
+ the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
+ exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
+ use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
+ to return a ScopedPointer as the result of a function. To avoid this causing errors,
+ ScopedPointer contains an overloaded constructor that should cause a syntax error in these
+ circumstances, but it does mean that instead of returning a ScopedPointer from a function,
+ you'd need to return a raw pointer (or use a std::auto_ptr instead).
+*/
+template <class ObjectType>
+class ScopedPointer
+{
+public:
+ //==============================================================================
+ /** Creates a ScopedPointer containing a null pointer. */
+ inline ScopedPointer() noexcept : object (nullptr)
+ {
+ }
+
+ /** Creates a ScopedPointer that owns the specified object. */
+ inline ScopedPointer (ObjectType* const objectToTakePossessionOf) noexcept
+ : object (objectToTakePossessionOf)
+ {
+ }
+
+ /** Creates a ScopedPointer that takes its pointer from another ScopedPointer.
+
+ Because a pointer can only belong to one ScopedPointer, this transfers
+ the pointer from the other object to this one, and the other object is reset to
+ be a null pointer.
+ */
+ ScopedPointer (ScopedPointer& objectToTransferFrom) noexcept
+ : object (objectToTransferFrom.object)
+ {
+ objectToTransferFrom.object = nullptr;
+ }
+
+ /** Destructor.
+ This will delete the object that this ScopedPointer currently refers to.
+ */
+ inline ~ScopedPointer() { ContainerDeletePolicy<ObjectType>::destroy (object); }
+
+ /** Changes this ScopedPointer to point to a new object.
+
+ Because a pointer can only belong to one ScopedPointer, this transfers
+ the pointer from the other object to this one, and the other object is reset to
+ be a null pointer.
+
+ If this ScopedPointer already points to an object, that object
+ will first be deleted.
+ */
+ ScopedPointer& operator= (ScopedPointer& objectToTransferFrom)
+ {
+ if (this != objectToTransferFrom.getAddress())
+ {
+ // Two ScopedPointers should never be able to refer to the same object - if
+ // this happens, you must have done something dodgy!
+ jassert (object == nullptr || object != objectToTransferFrom.object);
+
+ ObjectType* const oldObject = object;
+ object = objectToTransferFrom.object;
+ objectToTransferFrom.object = nullptr;
+ ContainerDeletePolicy<ObjectType>::destroy (oldObject);
+ }
+
+ return *this;
+ }
+
+ /** Changes this ScopedPointer to point to a new object.
+
+ If this ScopedPointer already points to an object, that object
+ will first be deleted.
+
+ The pointer that you pass in may be a nullptr.
+ */
+ ScopedPointer& operator= (ObjectType* const newObjectToTakePossessionOf)
+ {
+ if (object != newObjectToTakePossessionOf)
+ {
+ ObjectType* const oldObject = object;
+ object = newObjectToTakePossessionOf;
+ ContainerDeletePolicy<ObjectType>::destroy (oldObject);
+ }
+
+ return *this;
+ }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ ScopedPointer (ScopedPointer&& other) noexcept
+ : object (other.object)
+ {
+ other.object = nullptr;
+ }
+
+ ScopedPointer& operator= (ScopedPointer&& other) noexcept
+ {
+ object = other.object;
+ other.object = nullptr;
+ return *this;
+ }
+ #endif
+
+ //==============================================================================
+ /** Returns the object that this ScopedPointer refers to. */
+ inline operator ObjectType*() const noexcept { return object; }
+
+ /** Returns the object that this ScopedPointer refers to. */
+ inline ObjectType* get() const noexcept { return object; }
+
+ /** Returns the object that this ScopedPointer refers to. */
+ inline ObjectType& operator*() const noexcept { return *object; }
+
+ /** Lets you access methods and properties of the object that this ScopedPointer refers to. */
+ inline ObjectType* operator->() const noexcept { return object; }
+
+ //==============================================================================
+ /** Removes the current object from this ScopedPointer without deleting it.
+ This will return the current object, and set the ScopedPointer to a null pointer.
+ */
+ ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; }
+
+ //==============================================================================
+ /** Swaps this object with that of another ScopedPointer.
+ The two objects simply exchange their pointers.
+ */
+ void swapWith (ScopedPointer <ObjectType>& other) noexcept
+ {
+ // Two ScopedPointers should never be able to refer to the same object - if
+ // this happens, you must have done something dodgy!
+ jassert (object != other.object || this == other.getAddress());
+
+ std::swap (object, other.object);
+ }
+
+ /** If the pointer is non-null, this will attempt to return a new copy of the object that is pointed to.
+ If the pointer is null, this will safely return a nullptr.
+ */
+ inline ObjectType* createCopy() const { return createCopyIfNotNull (object); }
+
+private:
+ //==============================================================================
+ ObjectType* object;
+
+ // (Required as an alternative to the overloaded & operator).
+ const ScopedPointer* getAddress() const noexcept { return this; }
+
+ #if ! JUCE_MSVC // (MSVC can't deal with multiple copy constructors)
+ /* The copy constructors are private to stop people accidentally copying a const ScopedPointer
+ (the compiler would let you do so by implicitly casting the source to its raw object pointer).
+
+ A side effect of this is that in a compiler that doesn't support C++11, you may hit an
+ error when you write something like this:
+
+ ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private.
+
+ Even though the compiler would normally ignore the assignment here, it can't do so when the
+ copy constructor is private. It's very easy to fix though - just write it like this:
+
+ ScopedPointer<MyClass> m (new MyClass()); // Compiles OK
+
+ It's probably best to use the latter form when writing your object declarations anyway, as
+ this is a better representation of the code that you actually want the compiler to produce.
+ */
+ JUCE_DECLARE_NON_COPYABLE (ScopedPointer)
+ #endif
+};
+
+//==============================================================================
+/** Compares a ScopedPointer with another pointer.
+ This can be handy for checking whether this is a null pointer.
+*/
+template <class ObjectType>
+bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
+{
+ return static_cast <ObjectType*> (pointer1) == pointer2;
+}
+
+/** Compares a ScopedPointer with another pointer.
+ This can be handy for checking whether this is a null pointer.
+*/
+template <class ObjectType>
+bool operator!= (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
+{
+ return static_cast <ObjectType*> (pointer1) != pointer2;
+}
+
+//==============================================================================
+#ifndef DOXYGEN
+// NB: This is just here to prevent any silly attempts to call deleteAndZero() on a ScopedPointer.
+template <typename Type>
+void deleteAndZero (ScopedPointer<Type>&) { static_jassert (sizeof (Type) == 12345); }
+#endif
+
+#endif // JUCE_SCOPEDPOINTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_SharedResourcePointer.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_SharedResourcePointer.h
new file mode 100644
index 0000000..53d314b
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_SharedResourcePointer.h
@@ -0,0 +1,152 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
+#define JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A smart-pointer that automatically creates and manages the lifetime of a
+ shared static instance of a class.
+
+ The SharedObjectType template type indicates the class to use for the shared
+ object - the only requirements on this class are that it must have a public
+ default constructor and destructor.
+
+ The SharedResourcePointer offers a pattern that differs from using a singleton or
+ static instance of an object, because it uses reference-counting to make sure that
+ the underlying shared object is automatically created/destroyed according to the
+ number of SharedResourcePointer objects that exist. When the last one is deleted,
+ the underlying object is also immediately destroyed. This allows you to use scoping
+ to manage the lifetime of a shared resource.
+
+ Note: the construction/deletion of the shared object must not involve any
+ code that makes recursive calls to a SharedResourcePointer, or you'll cause
+ a deadlock.
+
+ Example:
+ @code
+ // An example of a class that contains the shared data you want to use.
+ struct MySharedData
+ {
+ // There's no need to ever create an instance of this class directly yourself,
+ // but it does need a public constructor that does the initialisation.
+ MySharedData()
+ {
+ sharedStuff = generateHeavyweightStuff();
+ }
+
+ Array<SomeKindOfData> sharedStuff;
+ };
+
+ struct DataUserClass
+ {
+ DataUserClass()
+ {
+ // Multiple instances of the DataUserClass will all have the same
+ // shared common instance of MySharedData referenced by their sharedData
+ // member variables.
+ useSharedStuff (sharedData->sharedStuff);
+ }
+
+ // By keeping this pointer as a member variable, the shared resource
+ // is guaranteed to be available for as long as the DataUserClass object.
+ SharedResourcePointer<MySharedData> sharedData;
+ };
+
+ @endcode
+ */
+template <typename SharedObjectType>
+class SharedResourcePointer
+{
+public:
+ /** Creates an instance of the shared object.
+ If other SharedResourcePointer objects for this type already exist, then
+ this one will simply point to the same shared object that they are already
+ using. Otherwise, if this is the first SharedResourcePointer to be created,
+ then a shared object will be created automatically.
+ */
+ SharedResourcePointer()
+ {
+ SharedObjectHolder& holder = getSharedObjectHolder();
+ const SpinLock::ScopedLockType sl (holder.lock);
+
+ if (++(holder.refCount) == 1)
+ holder.sharedInstance = new SharedObjectType();
+
+ sharedObject = holder.sharedInstance;
+ }
+
+ /** Destructor.
+ If no other SharedResourcePointer objects exist, this will also delete
+ the shared object to which it refers.
+ */
+ ~SharedResourcePointer()
+ {
+ SharedObjectHolder& holder = getSharedObjectHolder();
+ const SpinLock::ScopedLockType sl (holder.lock);
+
+ if (--(holder.refCount) == 0)
+ holder.sharedInstance = nullptr;
+ }
+
+ /** Returns the shared object. */
+ operator SharedObjectType*() const noexcept { return sharedObject; }
+
+ /** Returns the shared object. */
+ SharedObjectType& get() const noexcept { return *sharedObject; }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be zero, of course.
+ */
+ SharedObjectType& getObject() const noexcept { return *sharedObject; }
+
+ SharedObjectType* operator->() const noexcept { return sharedObject; }
+
+private:
+ struct SharedObjectHolder : public ReferenceCountedObject
+ {
+ SpinLock lock;
+ ScopedPointer<SharedObjectType> sharedInstance;
+ int refCount;
+ };
+
+ static SharedObjectHolder& getSharedObjectHolder() noexcept
+ {
+ static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { 0 };
+ return *reinterpret_cast<SharedObjectHolder*> (holder);
+ }
+
+ SharedObjectType* sharedObject;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedResourcePointer)
+};
+
+
+#endif // JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Singleton.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Singleton.h
new file mode 100644
index 0000000..00ea0af
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_Singleton.h
@@ -0,0 +1,292 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SINGLETON_H_INCLUDED
+#define JUCE_SINGLETON_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Macro to declare member variables and methods for a singleton class.
+
+ To use this, add the line juce_DeclareSingleton (MyClass, doNotRecreateAfterDeletion)
+ to the class's definition.
+
+ Then put a macro juce_ImplementSingleton (MyClass) along with the class's
+ implementation code.
+
+ It's also a very good idea to also add the call clearSingletonInstance() in your class's
+ destructor, in case it is deleted by other means than deleteInstance()
+
+ Clients can then call the static method MyClass::getInstance() to get a pointer
+ to the singleton, or MyClass::getInstanceWithoutCreating() which will return 0 if
+ no instance currently exists.
+
+ e.g. @code
+
+ class MySingleton
+ {
+ public:
+ MySingleton()
+ {
+ }
+
+ ~MySingleton()
+ {
+ // this ensures that no dangling pointers are left when the
+ // singleton is deleted.
+ clearSingletonInstance();
+ }
+
+ juce_DeclareSingleton (MySingleton, false)
+ };
+
+ juce_ImplementSingleton (MySingleton)
+
+
+ // example of usage:
+ MySingleton* m = MySingleton::getInstance(); // creates the singleton if there isn't already one.
+
+ ...
+
+ MySingleton::deleteInstance(); // safely deletes the singleton (if it's been created).
+
+ @endcode
+
+ If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
+ than once during the process's lifetime - i.e. after you've created and deleted the
+ object, getInstance() will refuse to create another one. This can be useful to stop
+ objects being accidentally re-created during your app's shutdown code.
+
+ If you know that your object will only be created and deleted by a single thread, you
+ can use the slightly more efficient juce_DeclareSingleton_SingleThreaded() macro instead
+ of this one.
+
+ @see juce_ImplementSingleton, juce_DeclareSingleton_SingleThreaded
+*/
+#define juce_DeclareSingleton(classname, doNotRecreateAfterDeletion) \
+\
+ static classname* _singletonInstance; \
+ static juce::CriticalSection _singletonLock; \
+\
+ static classname* JUCE_CALLTYPE getInstance() \
+ { \
+ if (_singletonInstance == nullptr) \
+ {\
+ const juce::ScopedLock sl (_singletonLock); \
+\
+ if (_singletonInstance == nullptr) \
+ { \
+ static bool alreadyInside = false; \
+ static bool createdOnceAlready = false; \
+\
+ const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
+ jassert (! problem); \
+ if (! problem) \
+ { \
+ createdOnceAlready = true; \
+ alreadyInside = true; \
+ classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
+ alreadyInside = false; \
+\
+ _singletonInstance = newObject; \
+ } \
+ } \
+ } \
+\
+ return _singletonInstance; \
+ } \
+\
+ static inline classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept\
+ { \
+ return _singletonInstance; \
+ } \
+\
+ static void JUCE_CALLTYPE deleteInstance() \
+ { \
+ const juce::ScopedLock sl (_singletonLock); \
+ if (_singletonInstance != nullptr) \
+ { \
+ classname* const old = _singletonInstance; \
+ _singletonInstance = nullptr; \
+ delete old; \
+ } \
+ } \
+\
+ void clearSingletonInstance() noexcept\
+ { \
+ if (_singletonInstance == this) \
+ _singletonInstance = nullptr; \
+ }
+
+
+//==============================================================================
+/** This is a counterpart to the juce_DeclareSingleton macro.
+
+ After adding the juce_DeclareSingleton to the class definition, this macro has
+ to be used in the cpp file.
+*/
+#define juce_ImplementSingleton(classname) \
+\
+ classname* classname::_singletonInstance = nullptr; \
+ juce::CriticalSection classname::_singletonLock;
+
+
+//==============================================================================
+/**
+ Macro to declare member variables and methods for a singleton class.
+
+ This is exactly the same as juce_DeclareSingleton, but doesn't use a critical
+ section to make access to it thread-safe. If you know that your object will
+ only ever be created or deleted by a single thread, then this is a
+ more efficient version to use.
+
+ If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
+ than once during the process's lifetime - i.e. after you've created and deleted the
+ object, getInstance() will refuse to create another one. This can be useful to stop
+ objects being accidentally re-created during your app's shutdown code.
+
+ See the documentation for juce_DeclareSingleton for more information about
+ how to use it, the only difference being that you have to use
+ juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.
+
+ @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton, juce_DeclareSingleton_SingleThreaded_Minimal
+*/
+#define juce_DeclareSingleton_SingleThreaded(classname, doNotRecreateAfterDeletion) \
+\
+ static classname* _singletonInstance; \
+\
+ static classname* getInstance() \
+ { \
+ if (_singletonInstance == nullptr) \
+ { \
+ static bool alreadyInside = false; \
+ static bool createdOnceAlready = false; \
+\
+ const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
+ jassert (! problem); \
+ if (! problem) \
+ { \
+ createdOnceAlready = true; \
+ alreadyInside = true; \
+ classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
+ alreadyInside = false; \
+\
+ _singletonInstance = newObject; \
+ } \
+ } \
+\
+ return _singletonInstance; \
+ } \
+\
+ static inline classname* getInstanceWithoutCreating() noexcept\
+ { \
+ return _singletonInstance; \
+ } \
+\
+ static void deleteInstance() \
+ { \
+ if (_singletonInstance != nullptr) \
+ { \
+ classname* const old = _singletonInstance; \
+ _singletonInstance = nullptr; \
+ delete old; \
+ } \
+ } \
+\
+ void clearSingletonInstance() noexcept\
+ { \
+ if (_singletonInstance == this) \
+ _singletonInstance = nullptr; \
+ }
+
+//==============================================================================
+/**
+ Macro to declare member variables and methods for a singleton class.
+
+ This is like juce_DeclareSingleton_SingleThreaded, but doesn't do any checking
+ for recursion or repeated instantiation. It's intended for use as a lightweight
+ version of a singleton, where you're using it in very straightforward
+ circumstances and don't need the extra checking.
+
+ Juce use the normal juce_ImplementSingleton_SingleThreaded as the counterpart
+ to this declaration, as you would with juce_DeclareSingleton_SingleThreaded.
+
+ See the documentation for juce_DeclareSingleton for more information about
+ how to use it, the only difference being that you have to use
+ juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.
+
+ @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton
+*/
+#define juce_DeclareSingleton_SingleThreaded_Minimal(classname) \
+\
+ static classname* _singletonInstance; \
+\
+ static classname* getInstance() \
+ { \
+ if (_singletonInstance == nullptr) \
+ _singletonInstance = new classname(); \
+\
+ return _singletonInstance; \
+ } \
+\
+ static inline classname* getInstanceWithoutCreating() noexcept\
+ { \
+ return _singletonInstance; \
+ } \
+\
+ static void deleteInstance() \
+ { \
+ if (_singletonInstance != nullptr) \
+ { \
+ classname* const old = _singletonInstance; \
+ _singletonInstance = nullptr; \
+ delete old; \
+ } \
+ } \
+\
+ void clearSingletonInstance() noexcept\
+ { \
+ if (_singletonInstance == this) \
+ _singletonInstance = nullptr; \
+ }
+
+
+//==============================================================================
+/** This is a counterpart to the juce_DeclareSingleton_SingleThreaded macro.
+
+ After adding juce_DeclareSingleton_SingleThreaded or juce_DeclareSingleton_SingleThreaded_Minimal
+ to the class definition, this macro has to be used somewhere in the cpp file.
+*/
+#define juce_ImplementSingleton_SingleThreaded(classname) \
+\
+ classname* classname::_singletonInstance = nullptr;
+
+
+
+#endif // JUCE_SINGLETON_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_WeakReference.h b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_WeakReference.h
new file mode 100644
index 0000000..b56808a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/memory/juce_WeakReference.h
@@ -0,0 +1,212 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_WEAKREFERENCE_H_INCLUDED
+#define JUCE_WEAKREFERENCE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ This class acts as a pointer which will automatically become null if the object
+ to which it points is deleted.
+
+ To accomplish this, the source object needs to cooperate by performing a couple of simple tasks.
+ It must embed a WeakReference::Master object, which stores a shared pointer object, and must clear
+ this master pointer in its destructor.
+
+ E.g.
+ @code
+ class MyObject
+ {
+ public:
+ MyObject()
+ {
+ // If you're planning on using your WeakReferences in a multi-threaded situation, you may choose
+ // to create a WeakReference to the object here in the constructor, which will pre-initialise the
+ // embedded object, avoiding an (extremely unlikely) race condition that could occur if multiple
+ // threads overlap while creating the first WeakReference to it.
+ }
+
+ ~MyObject()
+ {
+ // This will zero all the references - you need to call this in your destructor.
+ masterReference.clear();
+ }
+
+ private:
+ // You need to embed a variable of this type, with the name "masterReference" inside your object. If the
+ // variable is not public, you should make your class a friend of WeakReference<MyObject> so that the
+ // WeakReference class can access it.
+ WeakReference<MyObject>::Master masterReference;
+ friend class WeakReference<MyObject>;
+ };
+
+ // Here's an example of using a pointer..
+
+ MyObject* n = new MyObject();
+ WeakReference<MyObject> myObjectRef = n;
+
+ MyObject* pointer1 = myObjectRef; // returns a valid pointer to 'n'
+ delete n;
+ MyObject* pointer2 = myObjectRef; // returns a null pointer
+ @endcode
+
+ @see WeakReference::Master
+*/
+template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject>
+class WeakReference
+{
+public:
+ /** Creates a null SafePointer. */
+ inline WeakReference() noexcept {}
+
+ /** Creates a WeakReference that points at the given object. */
+ WeakReference (ObjectType* const object) : holder (getRef (object)) {}
+
+ /** Creates a copy of another WeakReference. */
+ WeakReference (const WeakReference& other) noexcept : holder (other.holder) {}
+
+ /** Copies another pointer to this one. */
+ WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; }
+
+ /** Copies another pointer to this one. */
+ WeakReference& operator= (ObjectType* const newObject) { holder = getRef (newObject); return *this; }
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ WeakReference (WeakReference&& other) noexcept : holder (static_cast <SharedRef&&> (other.holder)) {}
+ WeakReference& operator= (WeakReference&& other) noexcept { holder = static_cast <SharedRef&&> (other.holder); return *this; }
+ #endif
+
+ /** Returns the object that this pointer refers to, or null if the object no longer exists. */
+ ObjectType* get() const noexcept { return holder != nullptr ? holder->get() : nullptr; }
+
+ /** Returns the object that this pointer refers to, or null if the object no longer exists. */
+ operator ObjectType*() const noexcept { return get(); }
+
+ /** Returns the object that this pointer refers to, or null if the object no longer exists. */
+ ObjectType* operator->() noexcept { return get(); }
+
+ /** Returns the object that this pointer refers to, or null if the object no longer exists. */
+ const ObjectType* operator->() const noexcept { return get(); }
+
+ /** This returns true if this reference has been pointing at an object, but that object has
+ since been deleted.
+
+ If this reference was only ever pointing at a null pointer, this will return false. Using
+ operator=() to make this refer to a different object will reset this flag to match the status
+ of the reference from which you're copying.
+ */
+ bool wasObjectDeleted() const noexcept { return holder != nullptr && holder->get() == nullptr; }
+
+ bool operator== (ObjectType* const object) const noexcept { return get() == object; }
+ bool operator!= (ObjectType* const object) const noexcept { return get() != object; }
+
+ //==============================================================================
+ /** This class is used internally by the WeakReference class - don't use it directly
+ in your code!
+ @see WeakReference
+ */
+ class SharedPointer : public ReferenceCountingType
+ {
+ public:
+ explicit SharedPointer (ObjectType* const obj) noexcept : owner (obj) {}
+
+ inline ObjectType* get() const noexcept { return owner; }
+ void clearPointer() noexcept { owner = nullptr; }
+
+ private:
+ ObjectType* volatile owner;
+
+ JUCE_DECLARE_NON_COPYABLE (SharedPointer)
+ };
+
+ typedef ReferenceCountedObjectPtr<SharedPointer> SharedRef;
+
+ //==============================================================================
+ /**
+ This class is embedded inside an object to which you want to attach WeakReference pointers.
+ See the WeakReference class notes for an example of how to use this class.
+ @see WeakReference
+ */
+ class Master
+ {
+ public:
+ Master() noexcept {}
+
+ ~Master()
+ {
+ // You must remember to call clear() in your source object's destructor! See the notes
+ // for the WeakReference class for an example of how to do this.
+ jassert (sharedPointer == nullptr || sharedPointer->get() == nullptr);
+ }
+
+ /** The first call to this method will create an internal object that is shared by all weak
+ references to the object.
+ */
+ SharedPointer* getSharedPointer (ObjectType* const object)
+ {
+ if (sharedPointer == nullptr)
+ {
+ sharedPointer = new SharedPointer (object);
+ }
+ else
+ {
+ // You're trying to create a weak reference to an object that has already been deleted!!
+ jassert (sharedPointer->get() != nullptr);
+ }
+
+ return sharedPointer;
+ }
+
+ /** The object that owns this master pointer should call this before it gets destroyed,
+ to zero all the references to this object that may be out there. See the WeakReference
+ class notes for an example of how to do this.
+ */
+ void clear()
+ {
+ if (sharedPointer != nullptr)
+ sharedPointer->clearPointer();
+ }
+
+ private:
+ SharedRef sharedPointer;
+
+ JUCE_DECLARE_NON_COPYABLE (Master)
+ };
+
+private:
+ SharedRef holder;
+
+ static inline SharedPointer* getRef (ObjectType* const o)
+ {
+ return (o != nullptr) ? o->masterReference.getSharedPointer (o) : nullptr;
+ }
+};
+
+
+#endif // JUCE_WEAKREFERENCE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.cpp
new file mode 100644
index 0000000..1734907
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.cpp
@@ -0,0 +1,83 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Result::Result() noexcept {}
+
+Result::Result (const String& message) noexcept
+ : errorMessage (message)
+{
+}
+
+Result::Result (const Result& other)
+ : errorMessage (other.errorMessage)
+{
+}
+
+Result& Result::operator= (const Result& other)
+{
+ errorMessage = other.errorMessage;
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+Result::Result (Result&& other) noexcept
+ : errorMessage (static_cast <String&&> (other.errorMessage))
+{
+}
+
+Result& Result::operator= (Result&& other) noexcept
+{
+ errorMessage = static_cast <String&&> (other.errorMessage);
+ return *this;
+}
+#endif
+
+bool Result::operator== (const Result& other) const noexcept
+{
+ return errorMessage == other.errorMessage;
+}
+
+bool Result::operator!= (const Result& other) const noexcept
+{
+ return errorMessage != other.errorMessage;
+}
+
+Result Result::fail (const String& errorMessage) noexcept
+{
+ return Result (errorMessage.isEmpty() ? "Unknown Error" : errorMessage);
+}
+
+const String& Result::getErrorMessage() const noexcept
+{
+ return errorMessage;
+}
+
+bool Result::wasOk() const noexcept { return errorMessage.isEmpty(); }
+Result::operator bool() const noexcept { return errorMessage.isEmpty(); }
+bool Result::failed() const noexcept { return errorMessage.isNotEmpty(); }
+bool Result::operator!() const noexcept { return errorMessage.isNotEmpty(); }
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.h b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.h
new file mode 100644
index 0000000..7c320ac
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Result.h
@@ -0,0 +1,125 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_RESULT_H_INCLUDED
+#define JUCE_RESULT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents the 'success' or 'failure' of an operation, and holds an associated
+ error message to describe the error when there's a failure.
+
+ E.g.
+ @code
+ Result myOperation()
+ {
+ if (doSomeKindOfFoobar())
+ return Result::ok();
+ else
+ return Result::fail ("foobar didn't work!");
+ }
+
+ const Result result (myOperation());
+
+ if (result.wasOk())
+ {
+ ...it's all good...
+ }
+ else
+ {
+ warnUserAboutFailure ("The foobar operation failed! Error message was: "
+ + result.getErrorMessage());
+ }
+ @endcode
+*/
+class JUCE_API Result
+{
+public:
+ //==============================================================================
+ /** Creates and returns a 'successful' result. */
+ static Result ok() noexcept { return Result(); }
+
+ /** Creates a 'failure' result.
+ If you pass a blank error message in here, a default "Unknown Error" message
+ will be used instead.
+ */
+ static Result fail (const String& errorMessage) noexcept;
+
+ //==============================================================================
+ /** Returns true if this result indicates a success. */
+ bool wasOk() const noexcept;
+
+ /** Returns true if this result indicates a failure.
+ You can use getErrorMessage() to retrieve the error message associated
+ with the failure.
+ */
+ bool failed() const noexcept;
+
+ /** Returns true if this result indicates a success.
+ This is equivalent to calling wasOk().
+ */
+ operator bool() const noexcept;
+
+ /** Returns true if this result indicates a failure.
+ This is equivalent to calling failed().
+ */
+ bool operator!() const noexcept;
+
+ /** Returns the error message that was set when this result was created.
+ For a successful result, this will be an empty string;
+ */
+ const String& getErrorMessage() const noexcept;
+
+ //==============================================================================
+ Result (const Result&);
+ Result& operator= (const Result&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ Result (Result&&) noexcept;
+ Result& operator= (Result&&) noexcept;
+ #endif
+
+ bool operator== (const Result& other) const noexcept;
+ bool operator!= (const Result& other) const noexcept;
+
+private:
+ String errorMessage;
+
+ // The default constructor is not for public use!
+ // Instead, use Result::ok() or Result::fail()
+ Result() noexcept;
+ explicit Result (const String&) noexcept;
+
+ // These casts are private to prevent people trying to use the Result object in numeric contexts
+ operator int() const;
+ operator void*() const;
+};
+
+
+#endif // JUCE_RESULT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.cpp
new file mode 100644
index 0000000..eb74964
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.cpp
@@ -0,0 +1,117 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Uuid::Uuid()
+{
+ Random r;
+
+ for (size_t i = 0; i < sizeof (uuid); ++i)
+ uuid[i] = (uint8) (r.nextInt (256));
+
+ // To make it RFC 4122 compliant, need to force a few bits...
+ uuid[6] = (uuid[6] & 0x0f) | 0x40;
+ uuid[8] = (uuid[8] & 0x3f) | 0x80;
+}
+
+Uuid::~Uuid() noexcept {}
+
+Uuid::Uuid (const Uuid& other) noexcept
+{
+ memcpy (uuid, other.uuid, sizeof (uuid));
+}
+
+Uuid& Uuid::operator= (const Uuid& other) noexcept
+{
+ memcpy (uuid, other.uuid, sizeof (uuid));
+ return *this;
+}
+
+bool Uuid::operator== (const Uuid& other) const noexcept { return memcmp (uuid, other.uuid, sizeof (uuid)) == 0; }
+bool Uuid::operator!= (const Uuid& other) const noexcept { return ! operator== (other); }
+
+Uuid Uuid::null() noexcept
+{
+ return Uuid ((const uint8*) nullptr);
+}
+
+bool Uuid::isNull() const noexcept
+{
+ for (size_t i = 0; i < sizeof (uuid); ++i)
+ if (uuid[i] != 0)
+ return false;
+
+ return true;
+}
+
+String Uuid::getHexRegion (int start, int length) const
+{
+ return String::toHexString (uuid + start, length, 0);
+}
+
+String Uuid::toString() const
+{
+ return getHexRegion (0, 16);
+}
+
+String Uuid::toDashedString() const
+{
+ return getHexRegion (0, 4)
+ + "-" + getHexRegion (4, 2)
+ + "-" + getHexRegion (6, 2)
+ + "-" + getHexRegion (8, 2)
+ + "-" + getHexRegion (10, 6);
+}
+
+Uuid::Uuid (const String& uuidString)
+{
+ operator= (uuidString);
+}
+
+Uuid& Uuid::operator= (const String& uuidString)
+{
+ MemoryBlock mb;
+ mb.loadFromHexString (uuidString);
+ mb.ensureSize (sizeof (uuid), true);
+ mb.copyTo (uuid, 0, sizeof (uuid));
+ return *this;
+}
+
+Uuid::Uuid (const uint8* const rawData) noexcept
+{
+ operator= (rawData);
+}
+
+Uuid& Uuid::operator= (const uint8* const rawData) noexcept
+{
+ if (rawData != nullptr)
+ memcpy (uuid, rawData, sizeof (uuid));
+ else
+ zeromem (uuid, sizeof (uuid));
+
+ return *this;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.h b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.h
new file mode 100644
index 0000000..cd7af0d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_Uuid.h
@@ -0,0 +1,121 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_UUID_H_INCLUDED
+#define JUCE_UUID_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A universally unique 128-bit identifier.
+
+ This class generates very random unique numbers. It's vanishingly unlikely
+ that two identical UUIDs would ever be created by chance. The values are
+ formatted to meet the RFC 4122 version 4 standard.
+
+ The class includes methods for saving the ID as a string or as raw binary data.
+*/
+class JUCE_API Uuid
+{
+public:
+ //==============================================================================
+ /** Creates a new unique ID, compliant with RFC 4122 version 4. */
+ Uuid();
+
+ /** Destructor. */
+ ~Uuid() noexcept;
+
+ /** Creates a copy of another UUID. */
+ Uuid (const Uuid&) noexcept;
+
+ /** Copies another UUID. */
+ Uuid& operator= (const Uuid&) noexcept;
+
+ //==============================================================================
+ /** Returns true if the ID is zero. */
+ bool isNull() const noexcept;
+
+ /** Returns a null Uuid object. */
+ static Uuid null() noexcept;
+
+ bool operator== (const Uuid&) const noexcept;
+ bool operator!= (const Uuid&) const noexcept;
+
+ //==============================================================================
+ /** Returns a stringified version of this UUID.
+
+ A Uuid object can later be reconstructed from this string using operator= or
+ the constructor that takes a string parameter.
+
+ @returns a 32 character hex string.
+ */
+ String toString() const;
+
+ /** Returns a stringified version of this UUID, separating it into sections with dashes.
+ @returns a string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ */
+ String toDashedString() const;
+
+ /** Creates an ID from an encoded string version.
+ @see toString
+ */
+ Uuid (const String& uuidString);
+
+ /** Copies from a stringified UUID.
+ The string passed in should be one that was created with the toString() method.
+ */
+ Uuid& operator= (const String& uuidString);
+
+
+ //==============================================================================
+ /** Returns a pointer to the internal binary representation of the ID.
+
+ This is an array of 16 bytes. To reconstruct a Uuid from its data, use
+ the constructor or operator= method that takes an array of uint8s.
+ */
+ const uint8* getRawData() const noexcept { return uuid; }
+
+ /** Creates a UUID from a 16-byte array.
+ @see getRawData
+ */
+ Uuid (const uint8* rawData) noexcept;
+
+ /** Sets this UUID from 16-bytes of raw data. */
+ Uuid& operator= (const uint8* rawData) noexcept;
+
+
+private:
+ //==============================================================================
+ uint8 uuid[16];
+ String getHexRegion (int, int) const;
+
+ JUCE_LEAK_DETECTOR (Uuid)
+};
+
+
+#endif // JUCE_UUID_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_WindowsRegistry.h b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_WindowsRegistry.h
new file mode 100644
index 0000000..a1fb2a2
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/misc/juce_WindowsRegistry.h
@@ -0,0 +1,141 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_WINDOWSREGISTRY_H_INCLUDED
+#define JUCE_WINDOWSREGISTRY_H_INCLUDED
+
+#if JUCE_WINDOWS || DOXYGEN
+
+/**
+ Contains some static helper functions for manipulating the MS Windows registry
+ (Only available on Windows, of course!)
+*/
+class JUCE_API WindowsRegistry
+{
+public:
+ /** These values can be used to specify whether the 32- or 64-bit registry should be used.
+ When running on a 32-bit OS, there is no 64-bit registry, so the mode will be ignored.
+ */
+ enum WoW64Mode
+ {
+ /** Default handling: 32-bit apps will use the 32-bit registry, and 64-bit apps
+ will use the 64-bit registry. */
+ WoW64_Default = 0,
+
+ /** Always use the 64-bit registry store. (KEY_WOW64_64KEY). */
+ WoW64_64bit = 0x100,
+
+ /** Always use the 32-bit registry store. (KEY_WOW64_32KEY). */
+ WoW64_32bit = 0x200
+ };
+
+ //==============================================================================
+ /** Returns a string from the registry.
+ The path is a string for the entire path of a value in the registry,
+ e.g. "HKEY_CURRENT_USER\Software\foo\bar"
+ */
+ static String JUCE_CALLTYPE getValue (const String& regValuePath,
+ const String& defaultValue = String::empty,
+ WoW64Mode mode = WoW64_Default);
+
+ /** Reads a binary block from the registry.
+ The path is a string for the entire path of a value in the registry,
+ e.g. "HKEY_CURRENT_USER\Software\foo\bar"
+ @returns a DWORD indicating the type of the key.
+ */
+ static uint32 JUCE_CALLTYPE getBinaryValue (const String& regValuePath, MemoryBlock& resultData, WoW64Mode mode = WoW64_Default);
+
+ /** Sets a registry value as a string.
+ This will take care of creating any groups needed to get to the given registry value.
+ */
+ static bool JUCE_CALLTYPE setValue (const String& regValuePath, const String& value, WoW64Mode mode = WoW64_Default);
+
+ /** Sets a registry value as a DWORD.
+ This will take care of creating any groups needed to get to the given registry value.
+ */
+ static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint32 value, WoW64Mode mode = WoW64_Default);
+
+ /** Sets a registry value as a QWORD.
+ This will take care of creating any groups needed to get to the given registry value.
+ */
+ static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint64 value, WoW64Mode mode = WoW64_Default);
+
+ /** Sets a registry value as a binary block.
+ This will take care of creating any groups needed to get to the given registry value.
+ */
+ static bool JUCE_CALLTYPE setValue (const String& regValuePath, const MemoryBlock& value, WoW64Mode mode = WoW64_Default);
+
+ /** Returns true if the given value exists in the registry. */
+ static bool JUCE_CALLTYPE valueExists (const String& regValuePath, WoW64Mode mode = WoW64_Default);
+
+ /** Returns true if the given key exists in the registry. */
+ static bool JUCE_CALLTYPE keyExists (const String& regValuePath, WoW64Mode mode = WoW64_Default);
+
+ /** Deletes a registry value. */
+ static void JUCE_CALLTYPE deleteValue (const String& regValuePath, WoW64Mode mode = WoW64_Default);
+
+ /** Deletes a registry key (which is registry-talk for 'folder'). */
+ static void JUCE_CALLTYPE deleteKey (const String& regKeyPath, WoW64Mode mode = WoW64_Default);
+
+ /** Creates a file association in the registry.
+
+ This lets you set the executable that should be launched by a given file extension.
+ @param fileExtension the file extension to associate, including the
+ initial dot, e.g. ".txt"
+ @param symbolicDescription a space-free short token to identify the file type
+ @param fullDescription a human-readable description of the file type
+ @param targetExecutable the executable that should be launched
+ @param iconResourceNumber the icon that gets displayed for the file type will be
+ found by looking up this resource number in the
+ executable. Pass 0 here to not use an icon
+ @param registerForCurrentUserOnly if false, this will try to register the association
+ for all users (you might not have permission to do this
+ unless running in an installer). If true, it will register the
+ association in HKEY_CURRENT_USER.
+ @param mode the WoW64 mode to use for choosing the database
+ */
+ static bool JUCE_CALLTYPE registerFileAssociation (const String& fileExtension,
+ const String& symbolicDescription,
+ const String& fullDescription,
+ const File& targetExecutable,
+ int iconResourceNumber,
+ bool registerForCurrentUserOnly,
+ WoW64Mode mode = WoW64_Default);
+
+ // DEPRECATED: use the other methods with a WoW64Mode parameter of WoW64_64bit instead.
+ JUCE_DEPRECATED (static String getValueWow64 (const String&, const String& defaultValue = String::empty));
+ JUCE_DEPRECATED (static bool valueExistsWow64 (const String&));
+ JUCE_DEPRECATED (static bool keyExistsWow64 (const String&));
+
+private:
+ WindowsRegistry() JUCE_DELETED_FUNCTION;
+ JUCE_DECLARE_NON_COPYABLE (WindowsRegistry)
+};
+
+#endif
+#endif // JUCE_WINDOWSREGISTRY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/java/JuceAppActivity.java b/src/htio2/JUCE-3.0.8/modules/juce_core/native/java/JuceAppActivity.java
new file mode 100644
index 0000000..882d0e0
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/java/JuceAppActivity.java
@@ -0,0 +1,746 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission is granted to use this software under the terms of either:
+ a) the GPL v2 (or any later version)
+ b) the Affero GPL v3
+
+ Details of these licenses can be found at: www.gnu.org/licenses
+
+ JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ ------------------------------------------------------------------------------
+
+ To release a closed-source product which uses JUCE, commercial licenses are
+ available: visit www.juce.com for more information.
+
+ ==============================================================================
+*/
+
+package com.juce;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.*;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.graphics.*;
+import android.opengl.*;
+import android.text.ClipboardManager;
+import android.text.InputType;
+import android.util.DisplayMetrics;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.HttpURLConnection;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import android.media.AudioManager;
+import android.media.MediaScannerConnection;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+
+//==============================================================================
+public final class JuceAppActivity extends Activity
+{
+ //==============================================================================
+ static
+ {
+ System.loadLibrary ("juce_jni");
+ }
+
+ @Override
+ public final void onCreate (Bundle savedInstanceState)
+ {
+ super.onCreate (savedInstanceState);
+
+ viewHolder = new ViewHolder (this);
+ setContentView (viewHolder);
+
+ setVolumeControlStream (AudioManager.STREAM_MUSIC);
+ }
+
+ @Override
+ protected final void onDestroy()
+ {
+ quitApp();
+ super.onDestroy();
+ }
+
+ @Override
+ protected final void onPause()
+ {
+ if (viewHolder != null)
+ viewHolder.onPause();
+
+ suspendApp();
+ super.onPause();
+ }
+
+ @Override
+ protected final void onResume()
+ {
+ super.onResume();
+
+ if (viewHolder != null)
+ viewHolder.onResume();
+
+ resumeApp();
+ }
+
+ @Override
+ public void onConfigurationChanged (Configuration cfg)
+ {
+ super.onConfigurationChanged (cfg);
+ setContentView (viewHolder);
+ }
+
+ private void callAppLauncher()
+ {
+ launchApp (getApplicationInfo().publicSourceDir,
+ getApplicationInfo().dataDir);
+ }
+
+ //==============================================================================
+ private native void launchApp (String appFile, String appDataDir);
+ private native void quitApp();
+ private native void suspendApp();
+ private native void resumeApp();
+ private native void setScreenSize (int screenWidth, int screenHeight, int dpi);
+
+ //==============================================================================
+ public native void deliverMessage (long value);
+ private android.os.Handler messageHandler = new android.os.Handler();
+
+ public final void postMessage (long value)
+ {
+ messageHandler.post (new MessageCallback (value));
+ }
+
+ private final class MessageCallback implements Runnable
+ {
+ public MessageCallback (long value_) { value = value_; }
+ public final void run() { deliverMessage (value); }
+
+ private long value;
+ }
+
+ //==============================================================================
+ private ViewHolder viewHolder;
+
+ public final ComponentPeerView createNewView (boolean opaque, long host)
+ {
+ ComponentPeerView v = new ComponentPeerView (this, opaque, host);
+ viewHolder.addView (v);
+ return v;
+ }
+
+ public final void deleteView (ComponentPeerView view)
+ {
+ ViewGroup group = (ViewGroup) (view.getParent());
+
+ if (group != null)
+ group.removeView (view);
+ }
+
+ final class ViewHolder extends ViewGroup
+ {
+ public ViewHolder (Context context)
+ {
+ super (context);
+ setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ setFocusable (false);
+ }
+
+ protected final void onLayout (boolean changed, int left, int top, int right, int bottom)
+ {
+ setScreenSize (getWidth(), getHeight(), getDPI());
+
+ if (isFirstResize)
+ {
+ isFirstResize = false;
+ callAppLauncher();
+ }
+ }
+
+ public final void onPause()
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ {
+ View v = getChildAt (i);
+
+ if (v instanceof ComponentPeerView)
+ ((ComponentPeerView) v).onPause();
+ }
+ }
+
+ public final void onResume()
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ {
+ View v = getChildAt (i);
+
+ if (v instanceof ComponentPeerView)
+ ((ComponentPeerView) v).onResume();
+ }
+ }
+
+ private final int getDPI()
+ {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics (metrics);
+ return metrics.densityDpi;
+ }
+
+ private boolean isFirstResize = true;
+ }
+
+ public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom)
+ {
+ canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE);
+ }
+
+ //==============================================================================
+ public final String getClipboardContent()
+ {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
+ return clipboard.getText().toString();
+ }
+
+ public final void setClipboardContent (String newText)
+ {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
+ clipboard.setText (newText);
+ }
+
+ //==============================================================================
+ public final void showMessageBox (String title, String message, final long callback)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setPositiveButton ("OK", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public final void showOkCancelBox (String title, String message, final long callback)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setPositiveButton ("OK", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 1);
+ }
+ })
+ .setNegativeButton ("Cancel", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public final void showYesNoCancelBox (String title, String message, final long callback)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setPositiveButton ("Yes", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 1);
+ }
+ })
+ .setNegativeButton ("No", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 2);
+ }
+ })
+ .setNeutralButton ("Cancel", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.cancel();
+ JuceAppActivity.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public native void alertDismissed (long callback, int id);
+
+ //==============================================================================
+ public final class ComponentPeerView extends ViewGroup
+ implements View.OnFocusChangeListener
+ {
+ public ComponentPeerView (Context context, boolean opaque_, long host)
+ {
+ super (context);
+ this.host = host;
+ setWillNotDraw (false);
+ opaque = opaque_;
+
+ setFocusable (true);
+ setFocusableInTouchMode (true);
+ setOnFocusChangeListener (this);
+ requestFocus();
+ }
+
+ //==============================================================================
+ private native void handlePaint (long host, Canvas canvas);
+
+ @Override
+ public void onDraw (Canvas canvas)
+ {
+ handlePaint (host, canvas);
+ }
+
+ @Override
+ public boolean isOpaque()
+ {
+ return opaque;
+ }
+
+ private boolean opaque;
+ private long host;
+
+ //==============================================================================
+ private native void handleMouseDown (long host, int index, float x, float y, long time);
+ private native void handleMouseDrag (long host, int index, float x, float y, long time);
+ private native void handleMouseUp (long host, int index, float x, float y, long time);
+
+ @Override
+ public boolean onTouchEvent (MotionEvent event)
+ {
+ int action = event.getAction();
+ long time = event.getEventTime();
+
+ switch (action & MotionEvent.ACTION_MASK)
+ {
+ case MotionEvent.ACTION_DOWN:
+ handleMouseDown (host, event.getPointerId(0), event.getX(), event.getY(), time);
+ return true;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ handleMouseUp (host, event.getPointerId(0), event.getX(), event.getY(), time);
+ return true;
+
+ case MotionEvent.ACTION_MOVE:
+ {
+ int n = event.getPointerCount();
+ for (int i = 0; i < n; ++i)
+ handleMouseDrag (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+
+ return true;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP:
+ {
+ int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ handleMouseUp (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+ return true;
+ }
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ {
+ int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ handleMouseDown (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ //==============================================================================
+ private native void handleKeyDown (long host, int keycode, int textchar);
+ private native void handleKeyUp (long host, int keycode, int textchar);
+
+ public void showKeyboard (String type)
+ {
+ InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ {
+ if (type.length() > 0)
+ {
+ imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);
+ imm.setInputMethod (getWindowToken(), type);
+ }
+ else
+ {
+ imm.hideSoftInputFromWindow (getWindowToken(), 0);
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown (int keyCode, KeyEvent event)
+ {
+ switch (keyCode)
+ {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ return super.onKeyDown (keyCode, event);
+
+ default: break;
+ }
+
+ handleKeyDown (host, keyCode, event.getUnicodeChar());
+ return true;
+ }
+
+ @Override
+ public boolean onKeyUp (int keyCode, KeyEvent event)
+ {
+ handleKeyUp (host, keyCode, event.getUnicodeChar());
+ return true;
+ }
+
+ // this is here to make keyboard entry work on a Galaxy Tab2 10.1
+ @Override
+ public InputConnection onCreateInputConnection (EditorInfo outAttrs)
+ {
+ outAttrs.actionLabel = "";
+ outAttrs.hintText = "";
+ outAttrs.initialCapsMode = 0;
+ outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
+ outAttrs.label = "";
+ outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI;
+ outAttrs.inputType = InputType.TYPE_NULL;
+
+ return new BaseInputConnection (this, false);
+ }
+
+ //==============================================================================
+ @Override
+ protected void onSizeChanged (int w, int h, int oldw, int oldh)
+ {
+ super.onSizeChanged (w, h, oldw, oldh);
+ viewSizeChanged (host);
+ }
+
+ @Override
+ protected void onLayout (boolean changed, int left, int top, int right, int bottom)
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ requestTransparentRegion (getChildAt (i));
+ }
+
+ private native void viewSizeChanged (long host);
+
+ @Override
+ public void onFocusChange (View v, boolean hasFocus)
+ {
+ if (v == this)
+ focusChanged (host, hasFocus);
+ }
+
+ private native void focusChanged (long host, boolean hasFocus);
+
+ public void setViewName (String newName) {}
+
+ public boolean isVisible() { return getVisibility() == VISIBLE; }
+ public void setVisible (boolean b) { setVisibility (b ? VISIBLE : INVISIBLE); }
+
+ public boolean containsPoint (int x, int y)
+ {
+ return true; //xxx needs to check overlapping views
+ }
+
+ public final void onPause()
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ {
+ View v = getChildAt (i);
+
+ if (v instanceof OpenGLView)
+ ((OpenGLView) v).onPause();
+ }
+ }
+
+ public final void onResume()
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ {
+ View v = getChildAt (i);
+
+ if (v instanceof OpenGLView)
+ ((OpenGLView) v).onResume();
+ }
+ }
+
+ public OpenGLView createGLView()
+ {
+ OpenGLView glView = new OpenGLView (getContext());
+ addView (glView);
+ return glView;
+ }
+ }
+
+ //==============================================================================
+ public final class OpenGLView extends GLSurfaceView
+ implements GLSurfaceView.Renderer
+ {
+ OpenGLView (Context context)
+ {
+ super (context);
+ setEGLContextClientVersion (2);
+ setRenderer (this);
+ setRenderMode (RENDERMODE_WHEN_DIRTY);
+ }
+
+ @Override
+ public void onSurfaceCreated (GL10 unused, EGLConfig config)
+ {
+ contextCreated();
+ }
+
+ @Override
+ public void onSurfaceChanged (GL10 unused, int width, int height)
+ {
+ contextChangedSize();
+ }
+
+ @Override
+ public void onDrawFrame (GL10 unused)
+ {
+ render();
+ }
+
+ private native void contextCreated();
+ private native void contextChangedSize();
+ private native void render();
+ }
+
+ //==============================================================================
+ public final int[] renderGlyph (char glyph, Paint paint, android.graphics.Matrix matrix, Rect bounds)
+ {
+ Path p = new Path();
+ paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p);
+
+ RectF boundsF = new RectF();
+ p.computeBounds (boundsF, true);
+ matrix.mapRect (boundsF);
+
+ boundsF.roundOut (bounds);
+ bounds.left--;
+ bounds.right++;
+
+ final int w = bounds.width();
+ final int h = Math.max (1, bounds.height());
+
+ Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888);
+
+ Canvas c = new Canvas (bm);
+ matrix.postTranslate (-bounds.left, -bounds.top);
+ c.setMatrix (matrix);
+ c.drawPath (p, paint);
+
+ final int sizeNeeded = w * h;
+ if (cachedRenderArray.length < sizeNeeded)
+ cachedRenderArray = new int [sizeNeeded];
+
+ bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h);
+ bm.recycle();
+ return cachedRenderArray;
+ }
+
+ private int[] cachedRenderArray = new int [256];
+
+ //==============================================================================
+ public static class HTTPStream
+ {
+ public HTTPStream (HttpURLConnection connection_,
+ int[] statusCode, StringBuffer responseHeaders) throws IOException
+ {
+ connection = connection_;
+
+ try
+ {
+ inputStream = new BufferedInputStream (connection.getInputStream());
+ }
+ catch (IOException e)
+ {
+ if (connection.getResponseCode() < org.apache.http.HttpStatus.SC_BAD_REQUEST)
+ throw e;
+ }
+ finally
+ {
+ statusCode[0] = connection.getResponseCode();
+ }
+
+ if (statusCode[0] >= org.apache.http.HttpStatus.SC_BAD_REQUEST)
+ inputStream = connection.getErrorStream();
+ else
+ inputStream = connection.getInputStream();
+
+ for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet())
+ if (entry.getKey() != null && entry.getValue() != null)
+ responseHeaders.append (entry.getKey() + ": "
+ + android.text.TextUtils.join (",", entry.getValue()) + "\n");
+ }
+
+ public final void release()
+ {
+ try
+ {
+ inputStream.close();
+ }
+ catch (IOException e)
+ {}
+
+ connection.disconnect();
+ }
+
+ public final int read (byte[] buffer, int numBytes)
+ {
+ int num = 0;
+
+ try
+ {
+ num = inputStream.read (buffer, 0, numBytes);
+ }
+ catch (IOException e)
+ {}
+
+ if (num > 0)
+ position += num;
+
+ return num;
+ }
+
+ public final long getPosition() { return position; }
+ public final long getTotalLength() { return -1; }
+ public final boolean isExhausted() { return false; }
+ public final boolean setPosition (long newPos) { return false; }
+
+ private HttpURLConnection connection;
+ private InputStream inputStream;
+ private long position;
+ }
+
+ public static final HTTPStream createHTTPStream (String address,
+ boolean isPost, byte[] postData, String headers,
+ int timeOutMs, int[] statusCode,
+ StringBuffer responseHeaders)
+ {
+ try
+ {
+ HttpURLConnection connection = (HttpURLConnection) (new URL(address)
+ .openConnection());
+ if (connection != null)
+ {
+ try
+ {
+ if (isPost)
+ {
+ connection.setRequestMethod("POST");
+ connection.setConnectTimeout(timeOutMs);
+ connection.setDoOutput(true);
+ connection.setChunkedStreamingMode(0);
+ OutputStream out = connection.getOutputStream();
+ out.write(postData);
+ out.flush();
+ }
+
+ return new HTTPStream (connection, statusCode, responseHeaders);
+ }
+ catch (Throwable e)
+ {
+ connection.disconnect();
+ }
+ }
+ }
+ catch (Throwable e) {}
+
+ return null;
+ }
+
+ public final void launchURL (String url)
+ {
+ startActivity (new Intent (Intent.ACTION_VIEW, Uri.parse (url)));
+ }
+
+ public static final String getLocaleValue (boolean isRegion)
+ {
+ java.util.Locale locale = java.util.Locale.getDefault();
+
+ return isRegion ? locale.getDisplayCountry (java.util.Locale.US)
+ : locale.getDisplayLanguage (java.util.Locale.US);
+ }
+
+ //==============================================================================
+ private final class SingleMediaScanner implements MediaScannerConnectionClient
+ {
+ public SingleMediaScanner (Context context, String filename)
+ {
+ file = filename;
+ msc = new MediaScannerConnection (context, this);
+ msc.connect();
+ }
+
+ @Override
+ public void onMediaScannerConnected()
+ {
+ msc.scanFile (file, null);
+ }
+
+ @Override
+ public void onScanCompleted (String path, Uri uri)
+ {
+ msc.disconnect();
+ }
+
+ private MediaScannerConnection msc;
+ private String file;
+ }
+
+ public final void scanFile (String filename)
+ {
+ new SingleMediaScanner (this, filename);
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_BasicNativeHeaders.h b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_BasicNativeHeaders.h
new file mode 100644
index 0000000..cdaa0ef
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_BasicNativeHeaders.h
@@ -0,0 +1,223 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_BASICNATIVEHEADERS_H_INCLUDED
+#define JUCE_BASICNATIVEHEADERS_H_INCLUDED
+
+#include "../system/juce_TargetPlatform.h"
+#undef T
+
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS
+
+ #if JUCE_IOS
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+ #import <CoreData/CoreData.h>
+ #import <MobileCoreServices/MobileCoreServices.h>
+ #include <sys/fcntl.h>
+ #else
+ #define Point CarbonDummyPointName
+ #define Component CarbonDummyCompName
+ #import <Cocoa/Cocoa.h>
+ #import <CoreAudio/HostTime.h>
+ #undef Point
+ #undef Component
+ #include <sys/dir.h>
+ #endif
+
+ #include <sys/socket.h>
+ #include <sys/sysctl.h>
+ #include <sys/stat.h>
+ #include <sys/param.h>
+ #include <sys/mount.h>
+ #include <sys/utsname.h>
+ #include <sys/mman.h>
+ #include <fnmatch.h>
+ #include <utime.h>
+ #include <dlfcn.h>
+ #include <ifaddrs.h>
+ #include <net/if_dl.h>
+ #include <mach/mach_time.h>
+ #include <mach-o/dyld.h>
+ #include <objc/runtime.h>
+ #include <objc/objc.h>
+ #include <objc/message.h>
+
+//==============================================================================
+#elif JUCE_WINDOWS
+ #if JUCE_MSVC
+ #ifndef _CPPRTTI
+ #error "You're compiling without RTTI enabled! This is needed for a lot of JUCE classes, please update your compiler settings!"
+ #endif
+
+ #ifndef _CPPUNWIND
+ #error "You're compiling without exceptions enabled! This is needed for a lot of JUCE classes, please update your compiler settings!"
+ #endif
+
+ #pragma warning (push)
+ #pragma warning (disable : 4100 4201 4514 4312 4995)
+ #endif
+
+ #define STRICT 1
+ #define WIN32_LEAN_AND_MEAN 1
+ #if JUCE_MINGW
+ #define _WIN32_WINNT 0x0501
+ #else
+ #define _WIN32_WINNT 0x0600
+ #endif
+ #define _UNICODE 1
+ #define UNICODE 1
+ #ifndef _WIN32_IE
+ #define _WIN32_IE 0x0500
+ #endif
+
+ #include <windows.h>
+ #include <shellapi.h>
+ #include <tchar.h>
+ #include <stddef.h>
+ #include <ctime>
+ #include <wininet.h>
+ #include <nb30.h>
+ #include <iphlpapi.h>
+ #include <mapi.h>
+ #include <float.h>
+ #include <process.h>
+ #include <shlobj.h>
+ #include <shlwapi.h>
+ #include <mmsystem.h>
+
+ #if JUCE_MINGW
+ #include <basetyps.h>
+ #else
+ #include <crtdbg.h>
+ #include <comutil.h>
+ #endif
+
+ #undef PACKED
+
+ #if JUCE_MSVC
+ #pragma warning (pop)
+ #pragma warning (4: 4511 4512 4100 /*4365*/) // (enable some warnings that are turned off in VC8)
+ #endif
+
+ #if JUCE_MSVC && ! JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
+ #pragma comment (lib, "kernel32.lib")
+ #pragma comment (lib, "user32.lib")
+ #pragma comment (lib, "wininet.lib")
+ #pragma comment (lib, "advapi32.lib")
+ #pragma comment (lib, "ws2_32.lib")
+ #pragma comment (lib, "version.lib")
+ #pragma comment (lib, "shlwapi.lib")
+ #pragma comment (lib, "winmm.lib")
+
+ #ifdef _NATIVE_WCHAR_T_DEFINED
+ #ifdef _DEBUG
+ #pragma comment (lib, "comsuppwd.lib")
+ #else
+ #pragma comment (lib, "comsuppw.lib")
+ #endif
+ #else
+ #ifdef _DEBUG
+ #pragma comment (lib, "comsuppd.lib")
+ #else
+ #pragma comment (lib, "comsupp.lib")
+ #endif
+ #endif
+ #endif
+
+ /* Used with DynamicLibrary to simplify importing functions from a win32 DLL.
+
+ dll: the DynamicLibrary object
+ functionName: function to import
+ localFunctionName: name you want to use to actually call it (must be different)
+ returnType: the return type
+ params: list of params (bracketed)
+ */
+ #define JUCE_LOAD_WINAPI_FUNCTION(dll, functionName, localFunctionName, returnType, params) \
+ typedef returnType (WINAPI *type##localFunctionName) params; \
+ type##localFunctionName localFunctionName = (type##localFunctionName) dll.getFunction (#functionName);
+
+//==============================================================================
+#elif JUCE_LINUX
+ #include <sched.h>
+ #include <pthread.h>
+ #include <sys/time.h>
+ #include <errno.h>
+ #include <sys/stat.h>
+ #include <sys/dir.h>
+ #include <sys/ptrace.h>
+ #include <sys/vfs.h>
+ #include <sys/wait.h>
+ #include <sys/mman.h>
+ #include <fnmatch.h>
+ #include <utime.h>
+ #include <pwd.h>
+ #include <fcntl.h>
+ #include <dlfcn.h>
+ #include <netdb.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <sys/sysinfo.h>
+ #include <sys/file.h>
+ #include <sys/prctl.h>
+ #include <signal.h>
+ #include <stddef.h>
+
+//==============================================================================
+#elif JUCE_ANDROID
+ #include <jni.h>
+ #include <pthread.h>
+ #include <sched.h>
+ #include <sys/time.h>
+ #include <utime.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <dlfcn.h>
+ #include <sys/stat.h>
+ #include <sys/statfs.h>
+ #include <sys/ptrace.h>
+ #include <sys/sysinfo.h>
+ #include <sys/mman.h>
+ #include <pwd.h>
+ #include <dirent.h>
+ #include <fnmatch.h>
+ #include <sys/wait.h>
+#endif
+
+// Need to clear various moronic redefinitions made by system headers..
+#undef max
+#undef min
+#undef direct
+#undef check
+
+#endif // JUCE_BASICNATIVEHEADERS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Files.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Files.cpp
new file mode 100644
index 0000000..45903b1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Files.cpp
@@ -0,0 +1,104 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+bool File::isOnCDRomDrive() const
+{
+ return false;
+}
+
+bool File::isOnHardDisk() const
+{
+ return true;
+}
+
+bool File::isOnRemovableDrive() const
+{
+ return false;
+}
+
+String File::getVersion() const
+{
+ return String::empty;
+}
+
+File File::getSpecialLocation (const SpecialLocationType type)
+{
+ switch (type)
+ {
+ case userHomeDirectory:
+ case userDocumentsDirectory:
+ case userMusicDirectory:
+ case userMoviesDirectory:
+ case userPicturesDirectory:
+ case userApplicationDataDirectory:
+ case userDesktopDirectory:
+ return File (android.appDataDir);
+
+ case commonApplicationDataDirectory:
+ case commonDocumentsDirectory:
+ return File (android.appDataDir);
+
+ case globalApplicationsDirectory:
+ return File ("/system/app");
+
+ case tempDirectory:
+ return File (android.appDataDir).getChildFile (".temp");
+
+ case invokedExecutableFile:
+ case currentExecutableFile:
+ case currentApplicationFile:
+ case hostApplicationPath:
+ return juce_getExecutableFile();
+
+ default:
+ jassertfalse; // unknown type?
+ break;
+ }
+
+ return File();
+}
+
+bool File::moveToTrash() const
+{
+ if (! exists())
+ return true;
+
+ // TODO
+ return false;
+}
+
+JUCE_API bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters)
+{
+ const LocalRef<jstring> t (javaString (fileName));
+ android.activity.callVoidMethod (JuceAppActivity.launchURL, t.get());
+ return true;
+}
+
+void File::revealToUser() const
+{
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_JNIHelpers.h b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_JNIHelpers.h
new file mode 100644
index 0000000..8e8b07d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_JNIHelpers.h
@@ -0,0 +1,428 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ANDROID_JNIHELPERS_H_INCLUDED
+#define JUCE_ANDROID_JNIHELPERS_H_INCLUDED
+
+#if ! (defined (JUCE_ANDROID_ACTIVITY_CLASSNAME) && defined (JUCE_ANDROID_ACTIVITY_CLASSPATH))
+ #error "The JUCE_ANDROID_ACTIVITY_CLASSNAME and JUCE_ANDROID_ACTIVITY_CLASSPATH macros must be set!"
+#endif
+
+//==============================================================================
+extern JNIEnv* getEnv() noexcept;
+
+//==============================================================================
+class GlobalRef
+{
+public:
+ inline GlobalRef() noexcept : obj (0) {}
+ inline explicit GlobalRef (jobject o) : obj (retain (o)) {}
+ inline GlobalRef (const GlobalRef& other) : obj (retain (other.obj)) {}
+ ~GlobalRef() { clear(); }
+
+ inline void clear()
+ {
+ if (obj != 0)
+ {
+ getEnv()->DeleteGlobalRef (obj);
+ obj = 0;
+ }
+ }
+
+ inline GlobalRef& operator= (const GlobalRef& other)
+ {
+ jobject newObj = retain (other.obj);
+ clear();
+ obj = newObj;
+ return *this;
+ }
+
+ //==============================================================================
+ inline operator jobject() const noexcept { return obj; }
+ inline jobject get() const noexcept { return obj; }
+
+ //==============================================================================
+ #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \
+ returnType call##typeName##Method (jmethodID methodID, ... ) const \
+ { \
+ va_list args; \
+ va_start (args, methodID); \
+ returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \
+ va_end (args); \
+ return result; \
+ }
+
+ DECLARE_CALL_TYPE_METHOD (jobject, Object)
+ DECLARE_CALL_TYPE_METHOD (jboolean, Boolean)
+ DECLARE_CALL_TYPE_METHOD (jbyte, Byte)
+ DECLARE_CALL_TYPE_METHOD (jchar, Char)
+ DECLARE_CALL_TYPE_METHOD (jshort, Short)
+ DECLARE_CALL_TYPE_METHOD (jint, Int)
+ DECLARE_CALL_TYPE_METHOD (jlong, Long)
+ DECLARE_CALL_TYPE_METHOD (jfloat, Float)
+ DECLARE_CALL_TYPE_METHOD (jdouble, Double)
+ #undef DECLARE_CALL_TYPE_METHOD
+
+ void callVoidMethod (jmethodID methodID, ... ) const
+ {
+ va_list args;
+ va_start (args, methodID);
+ getEnv()->CallVoidMethodV (obj, methodID, args);
+ va_end (args);
+ }
+
+private:
+ //==============================================================================
+ jobject obj;
+
+ static inline jobject retain (jobject obj)
+ {
+ return obj == 0 ? 0 : getEnv()->NewGlobalRef (obj);
+ }
+};
+
+//==============================================================================
+template <typename JavaType>
+class LocalRef
+{
+public:
+ explicit inline LocalRef (JavaType o) noexcept : obj (o) {}
+ inline LocalRef (const LocalRef& other) noexcept : obj (retain (other.obj)) {}
+ ~LocalRef() { clear(); }
+
+ void clear()
+ {
+ if (obj != 0)
+ getEnv()->DeleteLocalRef (obj);
+ }
+
+ LocalRef& operator= (const LocalRef& other)
+ {
+ jobject newObj = retain (other.obj);
+ clear();
+ obj = newObj;
+ return *this;
+ }
+
+ inline operator JavaType() const noexcept { return obj; }
+ inline JavaType get() const noexcept { return obj; }
+
+private:
+ JavaType obj;
+
+ static JavaType retain (JavaType obj)
+ {
+ return obj == 0 ? 0 : (JavaType) getEnv()->NewLocalRef (obj);
+ }
+};
+
+//==============================================================================
+namespace
+{
+ String juceString (JNIEnv* env, jstring s)
+ {
+ const char* const utf8 = env->GetStringUTFChars (s, nullptr);
+ CharPointer_UTF8 utf8CP (utf8);
+ const String result (utf8CP);
+ env->ReleaseStringUTFChars (s, utf8);
+ return result;
+ }
+
+ String juceString (jstring s)
+ {
+ return juceString (getEnv(), s);
+ }
+
+ LocalRef<jstring> javaString (const String& s)
+ {
+ return LocalRef<jstring> (getEnv()->NewStringUTF (s.toUTF8()));
+ }
+
+ LocalRef<jstring> javaStringFromChar (const juce_wchar c)
+ {
+ char utf8[8] = { 0 };
+ CharPointer_UTF8 (utf8).write (c);
+ return LocalRef<jstring> (getEnv()->NewStringUTF (utf8));
+ }
+}
+
+//==============================================================================
+class JNIClassBase
+{
+public:
+ explicit JNIClassBase (const char* classPath);
+ virtual ~JNIClassBase();
+
+ inline operator jclass() const noexcept { return classRef; }
+
+ static void initialiseAllClasses (JNIEnv*);
+ static void releaseAllClasses (JNIEnv*);
+
+protected:
+ virtual void initialiseFields (JNIEnv*) = 0;
+
+ jmethodID resolveMethod (JNIEnv*, const char* methodName, const char* params);
+ jmethodID resolveStaticMethod (JNIEnv*, const char* methodName, const char* params);
+ jfieldID resolveField (JNIEnv*, const char* fieldName, const char* signature);
+ jfieldID resolveStaticField (JNIEnv*, const char* fieldName, const char* signature);
+
+private:
+ const char* const classPath;
+ jclass classRef;
+
+ static Array<JNIClassBase*>& getClasses();
+ void initialise (JNIEnv*);
+ void release (JNIEnv*);
+
+ JUCE_DECLARE_NON_COPYABLE (JNIClassBase)
+};
+
+//==============================================================================
+#define CREATE_JNI_METHOD(methodID, stringName, params) methodID = resolveMethod (env, stringName, params);
+#define CREATE_JNI_STATICMETHOD(methodID, stringName, params) methodID = resolveStaticMethod (env, stringName, params);
+#define CREATE_JNI_FIELD(fieldID, stringName, signature) fieldID = resolveField (env, stringName, signature);
+#define CREATE_JNI_STATICFIELD(fieldID, stringName, signature) fieldID = resolveStaticField (env, stringName, signature);
+#define DECLARE_JNI_METHOD(methodID, stringName, params) jmethodID methodID;
+#define DECLARE_JNI_FIELD(fieldID, stringName, signature) jfieldID fieldID;
+
+#define DECLARE_JNI_CLASS(CppClassName, javaPath) \
+ class CppClassName ## _Class : public JNIClassBase \
+ { \
+ public: \
+ CppClassName ## _Class() : JNIClassBase (javaPath) {} \
+ \
+ void initialiseFields (JNIEnv* env) \
+ { \
+ JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD); \
+ } \
+ \
+ JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD); \
+ }; \
+ static CppClassName ## _Class CppClassName;
+
+
+//==============================================================================
+#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \
+ extern "C" __attribute__ ((visibility("default"))) returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params
+
+//==============================================================================
+class AndroidSystem
+{
+public:
+ AndroidSystem();
+
+ void initialise (JNIEnv*, jobject activity, jstring appFile, jstring appDataDir);
+ void shutdown (JNIEnv*);
+
+ //==============================================================================
+ GlobalRef activity;
+ String appFile, appDataDir;
+ int screenWidth, screenHeight, dpi;
+};
+
+extern AndroidSystem android;
+
+//==============================================================================
+class ThreadLocalJNIEnvHolder
+{
+public:
+ ThreadLocalJNIEnvHolder() noexcept
+ : jvm (nullptr)
+ {
+ zeromem (threads, sizeof (threads));
+ zeromem (envs, sizeof (envs));
+ }
+
+ void initialise (JNIEnv* env)
+ {
+ // NB: the DLL can be left loaded by the JVM, so the same static
+ // objects can end up being reused by subsequent runs of the app
+ zeromem (threads, sizeof (threads));
+ zeromem (envs, sizeof (envs));
+
+ env->GetJavaVM (&jvm);
+ addEnv (env);
+ }
+
+ JNIEnv* attach() noexcept
+ {
+ if (android.activity != nullptr)
+ {
+ if (JNIEnv* env = attachToCurrentThread())
+ {
+ SpinLock::ScopedLockType sl (addRemoveLock);
+ return addEnv (env);
+ }
+
+ jassertfalse;
+ }
+
+ return nullptr;
+ }
+
+ void detach() noexcept
+ {
+ if (android.activity != nullptr)
+ {
+ jvm->DetachCurrentThread();
+
+ const pthread_t thisThread = pthread_self();
+
+ SpinLock::ScopedLockType sl (addRemoveLock);
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ threads[i] = 0;
+ }
+ }
+
+ JNIEnv* getOrAttach() noexcept
+ {
+ if (JNIEnv* env = get())
+ return env;
+
+ SpinLock::ScopedLockType sl (addRemoveLock);
+
+ if (JNIEnv* env = get())
+ return env;
+
+ if (JNIEnv* env = attachToCurrentThread())
+ return addEnv (env);
+
+ return nullptr;
+ }
+
+private:
+ JavaVM* jvm;
+ enum { maxThreads = 32 };
+ pthread_t threads [maxThreads];
+ JNIEnv* envs [maxThreads];
+ SpinLock addRemoveLock;
+
+ JNIEnv* addEnv (JNIEnv* env) noexcept
+ {
+ const pthread_t thisThread = pthread_self();
+
+ for (int i = 0; i < maxThreads; ++i)
+ {
+ if (threads[i] == 0)
+ {
+ envs[i] = env;
+ threads[i] = thisThread;
+ return env;
+ }
+ }
+
+ jassertfalse; // too many threads!
+ return nullptr;
+ }
+
+ JNIEnv* get() const noexcept
+ {
+ const pthread_t thisThread = pthread_self();
+
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ return envs[i];
+
+ return nullptr;
+ }
+
+ JNIEnv* attachToCurrentThread()
+ {
+ JNIEnv* env = nullptr;
+ jvm->AttachCurrentThread (&env, nullptr);
+ return env;
+ }
+};
+
+extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
+
+struct AndroidThreadScope
+{
+ AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
+ ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
+};
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
+ METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \
+ METHOD (postMessage, "postMessage", "(J)V") \
+ METHOD (finish, "finish", "()V") \
+ METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \
+ METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
+ METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
+ METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
+ STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
+ METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
+ METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ STATICMETHOD (getLocaleValue, "getLocaleValue", "(Z)Ljava/lang/String;") \
+ METHOD (scanFile, "scanFile", "(Ljava/lang/String;)V")
+
+DECLARE_JNI_CLASS (JuceAppActivity, JUCE_ANDROID_ACTIVITY_CLASSPATH);
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "<init>", "(I)V") \
+ METHOD (setColor, "setColor", "(I)V") \
+ METHOD (setAlpha, "setAlpha", "(I)V") \
+ METHOD (setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
+ METHOD (ascent, "ascent", "()F") \
+ METHOD (descent, "descent", "()F") \
+ METHOD (setTextSize, "setTextSize", "(F)V") \
+ METHOD (getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \
+ METHOD (setTextScaleX, "setTextScaleX", "(F)V") \
+ METHOD (getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
+ METHOD (setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
+
+DECLARE_JNI_CLASS (Paint, "android/graphics/Paint");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "<init>", "()V") \
+ METHOD (setValues, "setValues", "([F)V") \
+
+DECLARE_JNI_CLASS (Matrix, "android/graphics/Matrix");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "<init>", "(IIII)V") \
+ FIELD (left, "left", "I") \
+ FIELD (right, "right", "I") \
+ FIELD (top, "top", "I") \
+ FIELD (bottom, "bottom", "I") \
+
+DECLARE_JNI_CLASS (RectClass, "android/graphics/Rect");
+#undef JNI_CLASS_MEMBERS
+
+#endif // JUCE_ANDROID_JNIHELPERS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Misc.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Misc.cpp
new file mode 100644
index 0000000..d26adc1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Misc.cpp
@@ -0,0 +1,32 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+void Logger::outputDebugString (const String& text)
+{
+ __android_log_print (ANDROID_LOG_INFO, "JUCE", "%s", text.toUTF8().getAddress());
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Network.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Network.cpp
new file mode 100644
index 0000000..1b86dee
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Network.cpp
@@ -0,0 +1,181 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "<init>", "()V") \
+ METHOD (toString, "toString", "()Ljava/lang/String;") \
+
+DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (release, "release", "()V") \
+ METHOD (read, "read", "([BI)I") \
+ METHOD (getPosition, "getPosition", "()J") \
+ METHOD (getTotalLength, "getTotalLength", "()J") \
+ METHOD (isExhausted, "isExhausted", "()Z") \
+ METHOD (setPosition, "setPosition", "(J)Z") \
+
+DECLARE_JNI_CLASS (HTTPStream, JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream");
+#undef JNI_CLASS_MEMBERS
+
+
+//==============================================================================
+void MACAddress::findAllAddresses (Array<MACAddress>& result)
+{
+ // TODO
+}
+
+
+JUCE_API bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailAddress,
+ const String& emailSubject,
+ const String& bodyText,
+ const StringArray& filesToAttach)
+{
+ // TODO
+ return false;
+}
+
+
+//==============================================================================
+class WebInputStream : public InputStream
+{
+public:
+ WebInputStream (String address, bool isPost, const MemoryBlock& postData,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers, int timeOutMs, StringPairArray* responseHeaders)
+ : statusCode (0)
+ {
+ if (! address.contains ("://"))
+ address = "http://" + address;
+
+ JNIEnv* env = getEnv();
+
+ jbyteArray postDataArray = 0;
+
+ if (postData.getSize() > 0)
+ {
+ postDataArray = env->NewByteArray (postData.getSize());
+ env->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData());
+ }
+
+ LocalRef<jobject> responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor));
+
+ // Annoyingly, the android HTTP functions will choke on this call if you try to do it on the message
+ // thread. You'll need to move your networking code to a background thread to keep it happy..
+ jassert (Thread::getCurrentThread() != nullptr);
+
+ jintArray statusCodeArray = env->NewIntArray (1);
+ jassert (statusCodeArray != 0);
+
+ stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
+ JuceAppActivity.createHTTPStream,
+ javaString (address).get(),
+ (jboolean) isPost,
+ postDataArray,
+ javaString (headers).get(),
+ (jint) timeOutMs,
+ statusCodeArray,
+ responseHeaderBuffer.get()));
+
+ jint* const statusCodeElements = env->GetIntArrayElements (statusCodeArray, 0);
+ statusCode = statusCodeElements[0];
+ env->ReleaseIntArrayElements (statusCodeArray, statusCodeElements, 0);
+ env->DeleteLocalRef (statusCodeArray);
+
+ if (postDataArray != 0)
+ env->DeleteLocalRef (postDataArray);
+
+ if (stream != 0)
+ {
+ StringArray headerLines;
+
+ {
+ LocalRef<jstring> headersString ((jstring) env->CallObjectMethod (responseHeaderBuffer.get(),
+ StringBuffer.toString));
+ headerLines.addLines (juceString (env, headersString));
+ }
+
+ if (responseHeaders != 0)
+ {
+ for (int i = 0; i < headerLines.size(); ++i)
+ {
+ const String& header = headerLines[i];
+ const String key (header.upToFirstOccurrenceOf (": ", false, false));
+ const String value (header.fromFirstOccurrenceOf (": ", false, false));
+ const String previousValue ((*responseHeaders) [key]);
+
+ responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
+ }
+ }
+ }
+ }
+
+ ~WebInputStream()
+ {
+ if (stream != 0)
+ stream.callVoidMethod (HTTPStream.release);
+ }
+
+ //==============================================================================
+ bool isError() const { return stream == nullptr; }
+
+ bool isExhausted() override { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); }
+ int64 getTotalLength() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; }
+ int64 getPosition() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; }
+ bool setPosition (int64 wantedPos) override { return stream != nullptr && stream.callBooleanMethod (HTTPStream.setPosition, (jlong) wantedPos); }
+
+ int read (void* buffer, int bytesToRead) override
+ {
+ jassert (buffer != nullptr && bytesToRead >= 0);
+
+ if (stream == nullptr)
+ return 0;
+
+ JNIEnv* env = getEnv();
+
+ jbyteArray javaArray = env->NewByteArray (bytesToRead);
+
+ int numBytes = stream.callIntMethod (HTTPStream.read, javaArray, (jint) bytesToRead);
+
+ if (numBytes > 0)
+ env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast <jbyte*> (buffer));
+
+ env->DeleteLocalRef (javaArray);
+ return numBytes;
+ }
+
+ //==============================================================================
+ GlobalRef stream;
+ int statusCode;
+
+private:
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_SystemStats.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_SystemStats.cpp
new file mode 100644
index 0000000..8223b89
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_SystemStats.cpp
@@ -0,0 +1,315 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+JNIClassBase::JNIClassBase (const char* cp) : classPath (cp), classRef (0)
+{
+ getClasses().add (this);
+}
+
+JNIClassBase::~JNIClassBase()
+{
+ getClasses().removeFirstMatchingValue (this);
+}
+
+Array<JNIClassBase*>& JNIClassBase::getClasses()
+{
+ static Array<JNIClassBase*> classes;
+ return classes;
+}
+
+void JNIClassBase::initialise (JNIEnv* env)
+{
+ classRef = (jclass) env->NewGlobalRef (env->FindClass (classPath));
+ jassert (classRef != 0);
+
+ initialiseFields (env);
+}
+
+void JNIClassBase::release (JNIEnv* env)
+{
+ env->DeleteGlobalRef (classRef);
+}
+
+void JNIClassBase::initialiseAllClasses (JNIEnv* env)
+{
+ const Array<JNIClassBase*>& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->initialise (env);
+}
+
+void JNIClassBase::releaseAllClasses (JNIEnv* env)
+{
+ const Array<JNIClassBase*>& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->release (env);
+}
+
+jmethodID JNIClassBase::resolveMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jmethodID JNIClassBase::resolveStaticMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetStaticMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jfieldID JNIClassBase::resolveField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+jfieldID JNIClassBase::resolveStaticField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetStaticFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+//==============================================================================
+ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
+
+#if JUCE_DEBUG
+static bool systemInitialised = false;
+#endif
+
+JNIEnv* getEnv() noexcept
+{
+ #if JUCE_DEBUG
+ if (! systemInitialised)
+ {
+ DBG ("*** Call to getEnv() when system not initialised");
+ jassertfalse;
+ std::exit (EXIT_FAILURE);
+ }
+ #endif
+
+ return threadLocalJNIEnvHolder.getOrAttach();
+}
+
+extern "C" jint JNI_OnLoad (JavaVM*, void*)
+{
+ return JNI_VERSION_1_2;
+}
+
+//==============================================================================
+AndroidSystem::AndroidSystem() : screenWidth (0), screenHeight (0), dpi (160)
+{
+}
+
+void AndroidSystem::initialise (JNIEnv* env, jobject act, jstring file, jstring dataDir)
+{
+ screenWidth = screenHeight = 0;
+ dpi = 160;
+ JNIClassBase::initialiseAllClasses (env);
+
+ threadLocalJNIEnvHolder.initialise (env);
+ #if JUCE_DEBUG
+ systemInitialised = true;
+ #endif
+
+ activity = GlobalRef (act);
+ appFile = juceString (env, file);
+ appDataDir = juceString (env, dataDir);
+}
+
+void AndroidSystem::shutdown (JNIEnv* env)
+{
+ activity.clear();
+
+ #if JUCE_DEBUG
+ systemInitialised = false;
+ #endif
+
+ JNIClassBase::releaseAllClasses (env);
+}
+
+AndroidSystem android;
+
+//==============================================================================
+namespace AndroidStatsHelpers
+{
+ #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;")
+
+ DECLARE_JNI_CLASS (SystemClass, "java/lang/System");
+ #undef JNI_CLASS_MEMBERS
+
+ String getSystemProperty (const String& name)
+ {
+ return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (SystemClass,
+ SystemClass.getProperty,
+ javaString (name).get())));
+ }
+
+ String getLocaleValue (bool isRegion)
+ {
+ return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (JuceAppActivity,
+ JuceAppActivity.getLocaleValue,
+ isRegion)));
+ }
+
+ #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD)
+ DECLARE_JNI_CLASS (BuildClass, "android/os/Build");
+ #undef JNI_CLASS_MEMBERS
+
+ String getAndroidOsBuildValue (const char* fieldName)
+ {
+ return juceString (LocalRef<jstring> ((jstring) getEnv()->GetStaticObjectField (
+ BuildClass, getEnv()->GetStaticFieldID (BuildClass, fieldName, "Ljava/lang/String;"))));
+ }
+}
+
+//==============================================================================
+SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
+{
+ return Android;
+}
+
+String SystemStats::getOperatingSystemName()
+{
+ return "Android " + AndroidStatsHelpers::getSystemProperty ("os.version");
+}
+
+String SystemStats::getDeviceDescription()
+{
+ return AndroidStatsHelpers::getAndroidOsBuildValue ("MODEL")
+ + "-" + AndroidStatsHelpers::getAndroidOsBuildValue ("SERIAL");
+}
+
+bool SystemStats::isOperatingSystem64Bit()
+{
+ #if JUCE_64BIT
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+String SystemStats::getCpuVendor()
+{
+ return AndroidStatsHelpers::getSystemProperty ("os.arch");
+}
+
+int SystemStats::getCpuSpeedInMegaherz()
+{
+ return 0; // TODO
+}
+
+int SystemStats::getMemorySizeInMegabytes()
+{
+ #if __ANDROID_API__ >= 9
+ struct sysinfo sysi;
+
+ if (sysinfo (&sysi) == 0)
+ return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
+ #endif
+
+ return 0;
+}
+
+int SystemStats::getPageSize()
+{
+ return sysconf (_SC_PAGESIZE);
+}
+
+//==============================================================================
+String SystemStats::getLogonName()
+{
+ if (const char* user = getenv ("USER"))
+ return CharPointer_UTF8 (user);
+
+ if (struct passwd* const pw = getpwuid (getuid()))
+ return CharPointer_UTF8 (pw->pw_name);
+
+ return String::empty;
+}
+
+String SystemStats::getFullUserName()
+{
+ return getLogonName();
+}
+
+String SystemStats::getComputerName()
+{
+ char name [256] = { 0 };
+ if (gethostname (name, sizeof (name) - 1) == 0)
+ return name;
+
+ return String::empty;
+}
+
+
+String SystemStats::getUserLanguage() { return AndroidStatsHelpers::getLocaleValue (false); }
+String SystemStats::getUserRegion() { return AndroidStatsHelpers::getLocaleValue (true); }
+String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }
+
+//==============================================================================
+void CPUInformation::initialise() noexcept
+{
+ numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN));
+}
+
+//==============================================================================
+uint32 juce_millisecondsSinceStartup() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return t.tv_sec * 1000 + t.tv_nsec / 1000000;
+}
+
+int64 Time::getHighResolutionTicks() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
+}
+
+int64 Time::getHighResolutionTicksPerSecond() noexcept
+{
+ return 1000000; // (microseconds)
+}
+
+double Time::getMillisecondCounterHiRes() noexcept
+{
+ return getHighResolutionTicks() * 0.001;
+}
+
+bool Time::setSystemTimeToThisTime() const
+{
+ jassertfalse;
+ return false;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Threads.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Threads.cpp
new file mode 100644
index 0000000..981be9a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_android_Threads.cpp
@@ -0,0 +1,76 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+/*
+ Note that a lot of methods that you'd expect to find in this file actually
+ live in juce_posix_SharedCode.h!
+*/
+
+//==============================================================================
+// sets the process to 0=low priority, 1=normal, 2=high, 3=realtime
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)
+{
+ // TODO
+
+ struct sched_param param;
+ int policy, maxp, minp;
+
+ const int p = (int) prior;
+
+ if (p <= 1)
+ policy = SCHED_OTHER;
+ else
+ policy = SCHED_RR;
+
+ minp = sched_get_priority_min (policy);
+ maxp = sched_get_priority_max (policy);
+
+ if (p < 2)
+ param.sched_priority = 0;
+ else if (p == 2 )
+ // Set to middle of lower realtime priority range
+ param.sched_priority = minp + (maxp - minp) / 4;
+ else
+ // Set to middle of higher realtime priority range
+ param.sched_priority = minp + (3 * (maxp - minp) / 4);
+
+ pthread_setschedparam (pthread_self(), policy, ¶m);
+}
+
+JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger()
+{
+ return false;
+}
+
+JUCE_API bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
+{
+ return juce_isRunningUnderDebugger();
+}
+
+JUCE_API void JUCE_CALLTYPE Process::raisePrivilege() {}
+JUCE_API void JUCE_CALLTYPE Process::lowerPrivilege() {}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_CommonFile.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_CommonFile.cpp
new file mode 100644
index 0000000..2ce98b3
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_CommonFile.cpp
@@ -0,0 +1,153 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+bool File::copyInternal (const File& dest) const
+{
+ FileInputStream in (*this);
+
+ if (dest.deleteFile())
+ {
+ {
+ FileOutputStream out (dest);
+
+ if (out.failedToOpen())
+ return false;
+
+ if (out.writeFromInputStream (in, -1) == getSize())
+ return true;
+ }
+
+ dest.deleteFile();
+ }
+
+ return false;
+}
+
+void File::findFileSystemRoots (Array<File>& destArray)
+{
+ destArray.add (File ("/"));
+}
+
+bool File::isHidden() const
+{
+ return getFileName().startsWithChar ('.');
+}
+
+static String getLinkedFile (StringRef file)
+{
+ HeapBlock<char> buffer (8194);
+ const int numBytes = (int) readlink (file.text, buffer, 8192);
+ return String::fromUTF8 (buffer, jmax (0, numBytes));
+};
+
+bool File::isLink() const
+{
+ return getLinkedFile (getFullPathName()).isNotEmpty();
+}
+
+File File::getLinkedTarget() const
+{
+ String f (getLinkedFile (getFullPathName()));
+
+ if (f.isNotEmpty())
+ return getSiblingFile (f);
+
+ return *this;
+}
+
+//==============================================================================
+class DirectoryIterator::NativeIterator::Pimpl
+{
+public:
+ Pimpl (const File& directory, const String& wc)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8()))
+ {
+ }
+
+ ~Pimpl()
+ {
+ if (dir != nullptr)
+ closedir (dir);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ if (dir != nullptr)
+ {
+ const char* wildcardUTF8 = nullptr;
+
+ for (;;)
+ {
+ struct dirent* const de = readdir (dir);
+
+ if (de == nullptr)
+ break;
+
+ if (wildcardUTF8 == nullptr)
+ wildcardUTF8 = wildCard.toUTF8();
+
+ if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
+ {
+ filenameFound = CharPointer_UTF8 (de->d_name);
+
+ updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
+
+ if (isHidden != nullptr)
+ *isHidden = filenameFound.startsWithChar ('.');
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+private:
+ String parentDir, wildCard;
+ DIR* dir;
+
+ JUCE_DECLARE_NON_COPYABLE (Pimpl)
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
+{
+}
+
+DirectoryIterator::NativeIterator::~NativeIterator() {}
+
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* isDir, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Files.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Files.cpp
new file mode 100644
index 0000000..d0dd54d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Files.cpp
@@ -0,0 +1,241 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+enum
+{
+ U_ISOFS_SUPER_MAGIC = 0x9660, // linux/iso_fs.h
+ U_MSDOS_SUPER_MAGIC = 0x4d44, // linux/msdos_fs.h
+ U_NFS_SUPER_MAGIC = 0x6969, // linux/nfs_fs.h
+ U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h
+};
+
+bool File::isOnCDRomDrive() const
+{
+ struct statfs buf;
+
+ return statfs (getFullPathName().toUTF8(), &buf) == 0
+ && buf.f_type == (short) U_ISOFS_SUPER_MAGIC;
+}
+
+bool File::isOnHardDisk() const
+{
+ struct statfs buf;
+
+ if (statfs (getFullPathName().toUTF8(), &buf) == 0)
+ {
+ switch (buf.f_type)
+ {
+ case U_ISOFS_SUPER_MAGIC: // CD-ROM
+ case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
+ case U_NFS_SUPER_MAGIC: // Network NFS
+ case U_SMB_SUPER_MAGIC: // Network Samba
+ return false;
+
+ default: break;
+ }
+ }
+
+ // Assume so if this fails for some reason
+ return true;
+}
+
+bool File::isOnRemovableDrive() const
+{
+ jassertfalse; // xxx not implemented for linux!
+ return false;
+}
+
+String File::getVersion() const
+{
+ return String(); // xxx not yet implemented
+}
+
+//==============================================================================
+static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
+{
+ StringArray confLines;
+ File ("~/.config/user-dirs.dirs").readLines (confLines);
+
+ for (int i = 0; i < confLines.size(); ++i)
+ {
+ const String line (confLines[i].trimStart());
+
+ if (line.startsWith (type))
+ {
+ // eg. resolve XDG_MUSIC_DIR="$HOME/Music" to /home/user/Music
+ const File f (line.replace ("$HOME", File ("~").getFullPathName())
+ .fromFirstOccurrenceOf ("=", false, false)
+ .trim().unquoted());
+
+ if (f.isDirectory())
+ return f;
+ }
+ }
+
+ return File (fallbackFolder);
+}
+
+const char* const* juce_argv = nullptr;
+int juce_argc = 0;
+
+File File::getSpecialLocation (const SpecialLocationType type)
+{
+ switch (type)
+ {
+ case userHomeDirectory:
+ {
+ if (const char* homeDir = getenv ("HOME"))
+ return File (CharPointer_UTF8 (homeDir));
+
+ if (struct passwd* const pw = getpwuid (getuid()))
+ return File (CharPointer_UTF8 (pw->pw_dir));
+
+ return File();
+ }
+
+ case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~");
+ case userMusicDirectory: return resolveXDGFolder ("XDG_MUSIC_DIR", "~");
+ case userMoviesDirectory: return resolveXDGFolder ("XDG_VIDEOS_DIR", "~");
+ case userPicturesDirectory: return resolveXDGFolder ("XDG_PICTURES_DIR", "~");
+ case userDesktopDirectory: return resolveXDGFolder ("XDG_DESKTOP_DIR", "~/Desktop");
+ case userApplicationDataDirectory: return resolveXDGFolder ("XDG_CONFIG_HOME", "~");
+ case commonDocumentsDirectory:
+ case commonApplicationDataDirectory: return File ("/var");
+ case globalApplicationsDirectory: return File ("/usr");
+
+ case tempDirectory:
+ {
+ File tmp ("/var/tmp");
+
+ if (! tmp.isDirectory())
+ {
+ tmp = "/tmp";
+
+ if (! tmp.isDirectory())
+ tmp = File::getCurrentWorkingDirectory();
+ }
+
+ return tmp;
+ }
+
+ case invokedExecutableFile:
+ if (juce_argv != nullptr && juce_argc > 0)
+ return File (CharPointer_UTF8 (juce_argv[0]));
+ // deliberate fall-through...
+
+ case currentExecutableFile:
+ case currentApplicationFile:
+ return juce_getExecutableFile();
+
+ case hostApplicationPath:
+ {
+ const File f ("/proc/self/exe");
+ return f.isLink() ? f.getLinkedTarget() : juce_getExecutableFile();
+ }
+
+ default:
+ jassertfalse; // unknown type?
+ break;
+ }
+
+ return File();
+}
+
+//==============================================================================
+bool File::moveToTrash() const
+{
+ if (! exists())
+ return true;
+
+ File trashCan ("~/.Trash");
+
+ if (! trashCan.isDirectory())
+ trashCan = "~/.local/share/Trash/files";
+
+ if (! trashCan.isDirectory())
+ return false;
+
+ return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
+ getFileExtension()));
+}
+
+//==============================================================================
+static bool isFileExecutable (const String& filename)
+{
+ juce_statStruct info;
+
+ return juce_stat (filename, info)
+ && S_ISREG (info.st_mode)
+ && access (filename.toUTF8(), X_OK) == 0;
+}
+
+bool Process::openDocument (const String& fileName, const String& parameters)
+{
+ String cmdString (fileName.replace (" ", "\\ ",false));
+ cmdString << " " << parameters;
+
+ if (URL::isProbablyAWebsiteURL (fileName)
+ || cmdString.startsWithIgnoreCase ("file:")
+ || URL::isProbablyAnEmailAddress (fileName)
+ || File::createFileWithoutCheckingPath (fileName).isDirectory()
+ || ! isFileExecutable (fileName))
+ {
+ // create a command that tries to launch a bunch of likely browsers
+ static const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
+ "google-chrome", "chromium-browser", "opera", "konqueror" };
+ StringArray cmdLines;
+
+ for (int i = 0; i < numElementsInArray (browserNames); ++i)
+ cmdLines.add (String (browserNames[i]) + " " + cmdString.trim().quoted());
+
+ cmdString = cmdLines.joinIntoString (" || ");
+ }
+
+ const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
+
+ const int cpid = fork();
+
+ if (cpid == 0)
+ {
+ setsid();
+
+ // Child process
+ execve (argv[0], (char**) argv, environ);
+ exit (0);
+ }
+
+ return cpid >= 0;
+}
+
+void File::revealToUser() const
+{
+ if (isDirectory())
+ startAsProcess();
+ else if (getParentDirectory().exists())
+ getParentDirectory().startAsProcess();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Network.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Network.cpp
new file mode 100644
index 0000000..7543a77
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Network.cpp
@@ -0,0 +1,444 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+void MACAddress::findAllAddresses (Array<MACAddress>& result)
+{
+ const int s = socket (AF_INET, SOCK_DGRAM, 0);
+ if (s != -1)
+ {
+ char buf [1024];
+ struct ifconf ifc;
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ ioctl (s, SIOCGIFCONF, &ifc);
+
+ for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i)
+ {
+ struct ifreq ifr;
+ strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
+
+ if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0
+ && (ifr.ifr_flags & IFF_LOOPBACK) == 0
+ && ioctl (s, SIOCGIFHWADDR, &ifr) == 0)
+ {
+ MACAddress ma ((const uint8*) ifr.ifr_hwaddr.sa_data);
+
+ if (! ma.isNull())
+ result.addIfNotAlreadyThere (ma);
+ }
+ }
+
+ close (s);
+ }
+}
+
+
+bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEmailAddress */,
+ const String& /* emailSubject */,
+ const String& /* bodyText */,
+ const StringArray& /* filesToAttach */)
+{
+ jassertfalse; // xxx todo
+ return false;
+}
+
+
+//==============================================================================
+class WebInputStream : public InputStream
+{
+public:
+ WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
+ : statusCode (0), socketHandle (-1), levelsOfRedirection (0),
+ address (address_), headers (headers_), postData (postData_), position (0),
+ finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
+ {
+ statusCode = createConnection (progressCallback, progressCallbackContext);
+
+ if (responseHeaders != nullptr && ! isError())
+ {
+ for (int i = 0; i < headerLines.size(); ++i)
+ {
+ const String& headersEntry = headerLines[i];
+ const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
+ const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
+ const String previousValue ((*responseHeaders) [key]);
+ responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
+ }
+ }
+ }
+
+ ~WebInputStream()
+ {
+ closeSocket();
+ }
+
+ //==============================================================================
+ bool isError() const { return socketHandle < 0; }
+ bool isExhausted() override { return finished; }
+ int64 getPosition() override { return position; }
+
+ int64 getTotalLength() override
+ {
+ //xxx to do
+ return -1;
+ }
+
+ int read (void* buffer, int bytesToRead) override
+ {
+ if (finished || isError())
+ return 0;
+
+ fd_set readbits;
+ FD_ZERO (&readbits);
+ FD_SET (socketHandle, &readbits);
+
+ struct timeval tv;
+ tv.tv_sec = jmax (1, timeOutMs / 1000);
+ tv.tv_usec = 0;
+
+ if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
+ return 0; // (timeout)
+
+ const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
+ if (bytesRead == 0)
+ finished = true;
+
+ position += bytesRead;
+ return bytesRead;
+ }
+
+ bool setPosition (int64 wantedPos) override
+ {
+ if (isError())
+ return false;
+
+ if (wantedPos != position)
+ {
+ finished = false;
+
+ if (wantedPos < position)
+ {
+ closeSocket();
+ position = 0;
+ statusCode = createConnection (0, 0);
+ }
+
+ skipNextBytes (wantedPos - position);
+ }
+
+ return true;
+ }
+
+ //==============================================================================
+ int statusCode;
+
+private:
+ int socketHandle, levelsOfRedirection;
+ StringArray headerLines;
+ String address, headers;
+ MemoryBlock postData;
+ int64 position;
+ bool finished;
+ const bool isPost;
+ const int timeOutMs;
+
+ void closeSocket()
+ {
+ if (socketHandle >= 0)
+ close (socketHandle);
+
+ socketHandle = -1;
+ levelsOfRedirection = 0;
+ }
+
+ int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
+ {
+ closeSocket();
+
+ uint32 timeOutTime = Time::getMillisecondCounter();
+
+ if (timeOutMs == 0)
+ timeOutTime += 60000;
+ else if (timeOutMs < 0)
+ timeOutTime = 0xffffffff;
+ else
+ timeOutTime += timeOutMs;
+
+ String hostName, hostPath;
+ int hostPort;
+ if (! decomposeURL (address, hostName, hostPath, hostPort))
+ return 0;
+
+ String serverName, proxyName, proxyPath;
+ int proxyPort = 0;
+ int port = 0;
+
+ const String proxyURL (getenv ("http_proxy"));
+ if (proxyURL.startsWithIgnoreCase ("http://"))
+ {
+ if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
+ return 0;
+
+ serverName = proxyName;
+ port = proxyPort;
+ }
+ else
+ {
+ serverName = hostName;
+ port = hostPort;
+ }
+
+ struct addrinfo hints;
+ zerostruct (hints);
+
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ struct addrinfo* result = nullptr;
+ if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
+ return 0;
+
+ socketHandle = socket (result->ai_family, result->ai_socktype, 0);
+
+ if (socketHandle == -1)
+ {
+ freeaddrinfo (result);
+ return 0;
+ }
+
+ int receiveBufferSize = 16384;
+ setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
+ setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
+
+ #if JUCE_MAC
+ setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
+ #endif
+
+ if (connect (socketHandle, result->ai_addr, result->ai_addrlen) == -1)
+ {
+ closeSocket();
+ freeaddrinfo (result);
+ return 0;
+ }
+
+ freeaddrinfo (result);
+
+ {
+ const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
+ hostPath, address, headers, postData, isPost));
+
+ if (! sendHeader (socketHandle, requestHeader, timeOutTime,
+ progressCallback, progressCallbackContext))
+ {
+ closeSocket();
+ return 0;
+ }
+ }
+
+ String responseHeader (readResponse (socketHandle, timeOutTime));
+ position = 0;
+
+ if (responseHeader.isNotEmpty())
+ {
+ headerLines = StringArray::fromLines (responseHeader);
+
+ const int status = responseHeader.fromFirstOccurrenceOf (" ", false, false)
+ .substring (0, 3).getIntValue();
+
+ //int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
+ //bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
+
+ String location (findHeaderItem (headerLines, "Location:"));
+
+ if (status >= 300 && status < 400
+ && location.isNotEmpty() && location != address)
+ {
+ if (! location.startsWithIgnoreCase ("http://"))
+ location = "http://" + location;
+
+ if (++levelsOfRedirection <= 3)
+ {
+ address = location;
+ return createConnection (progressCallback, progressCallbackContext);
+ }
+ }
+ else
+ {
+ levelsOfRedirection = 0;
+ return status;
+ }
+ }
+
+ closeSocket();
+ return 0;
+ }
+
+ //==============================================================================
+ String readResponse (const int socketHandle, const uint32 timeOutTime)
+ {
+ int numConsecutiveLFs = 0;
+ MemoryOutputStream buffer;
+
+ while (numConsecutiveLFs < 2
+ && buffer.getDataSize() < 32768
+ && Time::getMillisecondCounter() <= timeOutTime
+ && ! (finished || isError()))
+ {
+ char c = 0;
+ if (read (&c, 1) != 1)
+ return String();
+
+ buffer.writeByte (c);
+
+ if (c == '\n')
+ ++numConsecutiveLFs;
+ else if (c != '\r')
+ numConsecutiveLFs = 0;
+ }
+
+ const String header (buffer.toString().trimEnd());
+
+ if (header.startsWithIgnoreCase ("HTTP/"))
+ return header;
+
+ return String();
+ }
+
+ static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value)
+ {
+ if (! headers.containsIgnoreCase (key))
+ dest << "\r\n" << key << ' ' << value;
+ }
+
+ static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port)
+ {
+ dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
+ }
+
+ static MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
+ const String& proxyName, const int proxyPort,
+ const String& hostPath, const String& originalURL,
+ const String& userHeaders, const MemoryBlock& postData,
+ const bool isPost)
+ {
+ MemoryOutputStream header;
+
+ if (proxyName.isEmpty())
+ writeHost (header, isPost, hostPath, hostName, hostPort);
+ else
+ writeHost (header, isPost, originalURL, proxyName, proxyPort);
+
+ writeValueIfNotPresent (header, userHeaders, "User-Agent:", "JUCE/" JUCE_STRINGIFY(JUCE_MAJOR_VERSION)
+ "." JUCE_STRINGIFY(JUCE_MINOR_VERSION)
+ "." JUCE_STRINGIFY(JUCE_BUILDNUMBER));
+ writeValueIfNotPresent (header, userHeaders, "Connection:", "close");
+
+ if (isPost)
+ writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize()));
+
+ header << "\r\n" << userHeaders
+ << "\r\n" << postData;
+
+ return header.getMemoryBlock();
+ }
+
+ static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
+ {
+ size_t totalHeaderSent = 0;
+
+ while (totalHeaderSent < requestHeader.getSize())
+ {
+ if (Time::getMillisecondCounter() > timeOutTime)
+ return false;
+
+ const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
+
+ if (send (socketHandle, static_cast <const char*> (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend)
+ return false;
+
+ totalHeaderSent += numToSend;
+
+ if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize()))
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool decomposeURL (const String& url, String& host, String& path, int& port)
+ {
+ if (! url.startsWithIgnoreCase ("http://"))
+ return false;
+
+ const int nextSlash = url.indexOfChar (7, '/');
+ int nextColon = url.indexOfChar (7, ':');
+ if (nextColon > nextSlash && nextSlash > 0)
+ nextColon = -1;
+
+ if (nextColon >= 0)
+ {
+ host = url.substring (7, nextColon);
+
+ if (nextSlash >= 0)
+ port = url.substring (nextColon + 1, nextSlash).getIntValue();
+ else
+ port = url.substring (nextColon + 1).getIntValue();
+ }
+ else
+ {
+ port = 80;
+
+ if (nextSlash >= 0)
+ host = url.substring (7, nextSlash);
+ else
+ host = url.substring (7);
+ }
+
+ if (nextSlash >= 0)
+ path = url.substring (nextSlash);
+ else
+ path = "/";
+
+ return true;
+ }
+
+ static String findHeaderItem (const StringArray& lines, const String& itemName)
+ {
+ for (int i = 0; i < lines.size(); ++i)
+ if (lines[i].startsWithIgnoreCase (itemName))
+ return lines[i].substring (itemName.length()).trim();
+
+ return String();
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_SystemStats.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_SystemStats.cpp
new file mode 100644
index 0000000..939edb4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_SystemStats.cpp
@@ -0,0 +1,191 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+void Logger::outputDebugString (const String& text)
+{
+ std::cerr << text << std::endl;
+}
+
+//==============================================================================
+SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
+{
+ return Linux;
+}
+
+String SystemStats::getOperatingSystemName()
+{
+ return "Linux";
+}
+
+bool SystemStats::isOperatingSystem64Bit()
+{
+ #if JUCE_64BIT
+ return true;
+ #else
+ //xxx not sure how to find this out?..
+ return false;
+ #endif
+}
+
+//==============================================================================
+namespace LinuxStatsHelpers
+{
+ String getCpuInfo (const char* const key)
+ {
+ StringArray lines;
+ File ("/proc/cpuinfo").readLines (lines);
+
+ for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order)
+ if (lines[i].upToFirstOccurrenceOf (":", false, false).trim().equalsIgnoreCase (key))
+ return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
+
+ return String();
+ }
+}
+
+String SystemStats::getDeviceDescription()
+{
+ return LinuxStatsHelpers::getCpuInfo ("Hardware");
+}
+
+String SystemStats::getCpuVendor()
+{
+ String v (LinuxStatsHelpers::getCpuInfo ("vendor_id"));
+
+ if (v.isEmpty())
+ v = LinuxStatsHelpers::getCpuInfo ("model name");
+
+ return v;
+}
+
+int SystemStats::getCpuSpeedInMegaherz()
+{
+ return roundToInt (LinuxStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue());
+}
+
+int SystemStats::getMemorySizeInMegabytes()
+{
+ struct sysinfo sysi;
+
+ if (sysinfo (&sysi) == 0)
+ return sysi.totalram * sysi.mem_unit / (1024 * 1024);
+
+ return 0;
+}
+
+int SystemStats::getPageSize()
+{
+ return sysconf (_SC_PAGESIZE);
+}
+
+//==============================================================================
+String SystemStats::getLogonName()
+{
+ if (const char* user = getenv ("USER"))
+ return CharPointer_UTF8 (user);
+
+ if (struct passwd* const pw = getpwuid (getuid()))
+ return CharPointer_UTF8 (pw->pw_name);
+
+ return String();
+}
+
+String SystemStats::getFullUserName()
+{
+ return getLogonName();
+}
+
+String SystemStats::getComputerName()
+{
+ char name [256] = { 0 };
+ if (gethostname (name, sizeof (name) - 1) == 0)
+ return name;
+
+ return String();
+}
+
+static String getLocaleValue (nl_item key)
+{
+ const char* oldLocale = ::setlocale (LC_ALL, "");
+ String result (String::fromUTF8 (nl_langinfo (key)));
+ ::setlocale (LC_ALL, oldLocale);
+ return result;
+}
+
+String SystemStats::getUserLanguage() { return getLocaleValue (_NL_IDENTIFICATION_LANGUAGE); }
+String SystemStats::getUserRegion() { return getLocaleValue (_NL_IDENTIFICATION_TERRITORY); }
+String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }
+
+//==============================================================================
+void CPUInformation::initialise() noexcept
+{
+ const String flags (LinuxStatsHelpers::getCpuInfo ("flags"));
+ hasMMX = flags.contains ("mmx");
+ hasSSE = flags.contains ("sse");
+ hasSSE2 = flags.contains ("sse2");
+ hasSSE3 = flags.contains ("sse3");
+ has3DNow = flags.contains ("3dnow");
+
+ numCpus = LinuxStatsHelpers::getCpuInfo ("processor").getIntValue() + 1;
+}
+
+//==============================================================================
+uint32 juce_millisecondsSinceStartup() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return t.tv_sec * 1000 + t.tv_nsec / 1000000;
+}
+
+int64 Time::getHighResolutionTicks() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
+}
+
+int64 Time::getHighResolutionTicksPerSecond() noexcept
+{
+ return 1000000; // (microseconds)
+}
+
+double Time::getMillisecondCounterHiRes() noexcept
+{
+ return getHighResolutionTicks() * 0.001;
+}
+
+bool Time::setSystemTimeToThisTime() const
+{
+ timeval t;
+ t.tv_sec = millisSinceEpoch / 1000;
+ t.tv_usec = (millisSinceEpoch - t.tv_sec * 1000) * 1000;
+
+ return settimeofday (&t, 0) == 0;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Threads.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Threads.cpp
new file mode 100644
index 0000000..659fbd9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_linux_Threads.cpp
@@ -0,0 +1,90 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+/*
+ Note that a lot of methods that you'd expect to find in this file actually
+ live in juce_posix_SharedCode.h!
+*/
+
+//==============================================================================
+JUCE_API void JUCE_CALLTYPE Process::setPriority (const ProcessPriority prior)
+{
+ const int policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;
+ const int minp = sched_get_priority_min (policy);
+ const int maxp = sched_get_priority_max (policy);
+
+ struct sched_param param;
+
+ switch (prior)
+ {
+ case LowPriority:
+ case NormalPriority: param.sched_priority = 0; break;
+ case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;
+ case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;
+ default: jassertfalse; break;
+ }
+
+ pthread_setschedparam (pthread_self(), policy, ¶m);
+}
+
+JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger()
+{
+ #if JUCE_BSD
+ return false;
+ #else
+ static char testResult = 0;
+
+ if (testResult == 0)
+ {
+ testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0);
+
+ if (testResult >= 0)
+ {
+ ptrace (PT_DETACH, 0, (caddr_t) 1, 0);
+ testResult = 1;
+ }
+ }
+
+ return testResult < 0;
+ #endif
+}
+
+JUCE_API bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
+{
+ return juce_isRunningUnderDebugger();
+}
+
+static bool swapUserAndEffectiveUser()
+{
+ int result1 = setreuid (geteuid(), getuid());
+ int result2 = setregid (getegid(), getgid());
+ return result1 == 0 && result2 == 0;
+}
+
+JUCE_API void JUCE_CALLTYPE Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); }
+JUCE_API void JUCE_CALLTYPE Process::lowerPrivilege() { if (geteuid() == 0 && getuid() != 0) swapUserAndEffectiveUser(); }
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Files.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Files.mm
new file mode 100644
index 0000000..0a00e92
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Files.mm
@@ -0,0 +1,498 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+/*
+ Note that a lot of methods that you'd expect to find in this file actually
+ live in juce_posix_SharedCode.h!
+*/
+
+//==============================================================================
+bool File::copyInternal (const File& dest) const
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ NSFileManager* fm = [NSFileManager defaultManager];
+
+ return [fm fileExistsAtPath: juceStringToNS (fullPath)]
+ #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ && [fm copyItemAtPath: juceStringToNS (fullPath)
+ toPath: juceStringToNS (dest.getFullPathName())
+ error: nil];
+ #else
+ && [fm copyPath: juceStringToNS (fullPath)
+ toPath: juceStringToNS (dest.getFullPathName())
+ handler: nil];
+ #endif
+ }
+}
+
+void File::findFileSystemRoots (Array<File>& destArray)
+{
+ destArray.add (File ("/"));
+}
+
+
+//==============================================================================
+namespace FileHelpers
+{
+ static bool isFileOnDriveType (const File& f, const char* const* types)
+ {
+ struct statfs buf;
+
+ if (juce_doStatFS (f, buf))
+ {
+ const String type (buf.f_fstypename);
+
+ while (*types != 0)
+ if (type.equalsIgnoreCase (*types++))
+ return true;
+ }
+
+ return false;
+ }
+
+ static bool isHiddenFile (const String& path)
+ {
+ #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+ JUCE_AUTORELEASEPOOL
+ {
+ NSNumber* hidden = nil;
+ NSError* err = nil;
+
+ return [[NSURL fileURLWithPath: juceStringToNS (path)]
+ getResourceValue: &hidden forKey: NSURLIsHiddenKey error: &err]
+ && [hidden boolValue];
+ }
+ #elif JUCE_IOS
+ return File (path).getFileName().startsWithChar ('.');
+ #else
+ FSRef ref;
+ LSItemInfoRecord info;
+
+ return FSPathMakeRefWithOptions ((const UInt8*) path.toRawUTF8(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0) == noErr
+ && LSCopyItemInfoForRef (&ref, kLSRequestBasicFlagsOnly, &info) == noErr
+ && (info.flags & kLSItemInfoIsInvisible) != 0;
+ #endif
+ }
+
+ #if JUCE_IOS
+ static String getIOSSystemLocation (NSSearchPathDirectory type)
+ {
+ return nsStringToJuce ([NSSearchPathForDirectoriesInDomains (type, NSUserDomainMask, YES)
+ objectAtIndex: 0]);
+ }
+ #endif
+
+ static bool launchExecutable (const String& pathAndArguments)
+ {
+ const char* const argv[4] = { "/bin/sh", "-c", pathAndArguments.toUTF8(), 0 };
+
+ const int cpid = fork();
+
+ if (cpid == 0)
+ {
+ // Child process
+ if (execve (argv[0], (char**) argv, 0) < 0)
+ exit (0);
+ }
+ else
+ {
+ if (cpid < 0)
+ return false;
+ }
+
+ return true;
+ }
+}
+
+bool File::isOnCDRomDrive() const
+{
+ static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", nullptr };
+
+ return FileHelpers::isFileOnDriveType (*this, cdTypes);
+}
+
+bool File::isOnHardDisk() const
+{
+ static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", nullptr };
+
+ return ! (isOnCDRomDrive() || FileHelpers::isFileOnDriveType (*this, nonHDTypes));
+}
+
+bool File::isOnRemovableDrive() const
+{
+ #if JUCE_IOS
+ return false; // xxx is this possible?
+ #else
+ JUCE_AUTORELEASEPOOL
+ {
+ BOOL removable = false;
+
+ [[NSWorkspace sharedWorkspace]
+ getFileSystemInfoForPath: juceStringToNS (getFullPathName())
+ isRemovable: &removable
+ isWritable: nil
+ isUnmountable: nil
+ description: nil
+ type: nil];
+
+ return removable;
+ }
+ #endif
+}
+
+bool File::isHidden() const
+{
+ return FileHelpers::isHiddenFile (getFullPathName());
+}
+
+//==============================================================================
+const char* const* juce_argv = nullptr;
+int juce_argc = 0;
+
+File File::getSpecialLocation (const SpecialLocationType type)
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ String resultPath;
+
+ switch (type)
+ {
+ case userHomeDirectory: resultPath = nsStringToJuce (NSHomeDirectory()); break;
+
+ #if JUCE_IOS
+ case userDocumentsDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDocumentDirectory); break;
+ case userDesktopDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDesktopDirectory); break;
+
+ case tempDirectory:
+ {
+ File tmp (FileHelpers::getIOSSystemLocation (NSCachesDirectory));
+ tmp = tmp.getChildFile (juce_getExecutableFile().getFileNameWithoutExtension());
+ tmp.createDirectory();
+ return tmp.getFullPathName();
+ }
+
+ #else
+ case userDocumentsDirectory: resultPath = "~/Documents"; break;
+ case userDesktopDirectory: resultPath = "~/Desktop"; break;
+
+ case tempDirectory:
+ {
+ File tmp ("~/Library/Caches/" + juce_getExecutableFile().getFileNameWithoutExtension());
+ tmp.createDirectory();
+ return File (tmp.getFullPathName());
+ }
+ #endif
+ case userMusicDirectory: resultPath = "~/Music"; break;
+ case userMoviesDirectory: resultPath = "~/Movies"; break;
+ case userPicturesDirectory: resultPath = "~/Pictures"; break;
+ case userApplicationDataDirectory: resultPath = "~/Library"; break;
+ case commonApplicationDataDirectory: resultPath = "/Library"; break;
+ case commonDocumentsDirectory: resultPath = "/Users/Shared"; break;
+ case globalApplicationsDirectory: resultPath = "/Applications"; break;
+
+ case invokedExecutableFile:
+ if (juce_argv != nullptr && juce_argc > 0)
+ return File (CharPointer_UTF8 (juce_argv[0]));
+ // deliberate fall-through...
+
+ case currentExecutableFile:
+ return juce_getExecutableFile();
+
+ case currentApplicationFile:
+ {
+ const File exe (juce_getExecutableFile());
+ const File parent (exe.getParentDirectory());
+
+ #if JUCE_IOS
+ return parent;
+ #else
+ return parent.getFullPathName().endsWithIgnoreCase ("Contents/MacOS")
+ ? parent.getParentDirectory().getParentDirectory()
+ : exe;
+ #endif
+ }
+
+ case hostApplicationPath:
+ {
+ unsigned int size = 8192;
+ HeapBlock<char> buffer;
+ buffer.calloc (size + 8);
+
+ _NSGetExecutablePath (buffer.getData(), &size);
+ return File (String::fromUTF8 (buffer, (int) size));
+ }
+
+ default:
+ jassertfalse; // unknown type?
+ break;
+ }
+
+ if (resultPath.isNotEmpty())
+ return File (resultPath.convertToPrecomposedUnicode());
+ }
+
+ return File();
+}
+
+//==============================================================================
+String File::getVersion() const
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ if (NSBundle* bundle = [NSBundle bundleWithPath: juceStringToNS (getFullPathName())])
+ if (NSDictionary* info = [bundle infoDictionary])
+ if (NSString* name = [info valueForKey: nsStringLiteral ("CFBundleShortVersionString")])
+ return nsStringToJuce (name);
+ }
+
+ return String();
+}
+
+//==============================================================================
+static NSString* getFileLink (const String& path)
+{
+ #if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+ return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (path) error: nil];
+ #else
+ // (the cast here avoids a deprecation warning)
+ return [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: juceStringToNS (path)];
+ #endif
+}
+
+bool File::isLink() const
+{
+ return getFileLink (fullPath) != nil;
+}
+
+File File::getLinkedTarget() const
+{
+ if (NSString* dest = getFileLink (fullPath))
+ return getSiblingFile (nsStringToJuce (dest));
+
+ return *this;
+}
+
+//==============================================================================
+bool File::moveToTrash() const
+{
+ if (! exists())
+ return true;
+
+ #if JUCE_IOS
+ return deleteFile(); //xxx is there a trashcan on the iOS?
+ #else
+ JUCE_AUTORELEASEPOOL
+ {
+ NSString* p = juceStringToNS (getFullPathName());
+
+ return [[NSWorkspace sharedWorkspace]
+ performFileOperation: NSWorkspaceRecycleOperation
+ source: [p stringByDeletingLastPathComponent]
+ destination: nsEmptyString()
+ files: [NSArray arrayWithObject: [p lastPathComponent]]
+ tag: nil ];
+ }
+ #endif
+}
+
+//==============================================================================
+class DirectoryIterator::NativeIterator::Pimpl
+{
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ enumerator (nil)
+ {
+ JUCE_AUTORELEASEPOOL
+ {
+ enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain];
+ }
+ }
+
+ ~Pimpl()
+ {
+ [enumerator release];
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ JUCE_AUTORELEASEPOOL
+ {
+ const char* wildcardUTF8 = nullptr;
+
+ for (;;)
+ {
+ NSString* file;
+ if (enumerator == nil || (file = [enumerator nextObject]) == nil)
+ return false;
+
+ [enumerator skipDescendents];
+ filenameFound = nsStringToJuce (file).convertToPrecomposedUnicode();
+
+ if (wildcardUTF8 == nullptr)
+ wildcardUTF8 = wildCard.toUTF8();
+
+ if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0)
+ continue;
+
+ const String fullPath (parentDir + filenameFound);
+ updateStatInfoForFile (fullPath, isDir, fileSize, modTime, creationTime, isReadOnly);
+
+ if (isHidden != nullptr)
+ *isHidden = FileHelpers::isHiddenFile (fullPath);
+
+ return true;
+ }
+ }
+ }
+
+private:
+ String parentDir, wildCard;
+ NSDirectoryEnumerator* enumerator;
+
+ JUCE_DECLARE_NON_COPYABLE (Pimpl)
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildcard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildcard))
+{
+}
+
+DirectoryIterator::NativeIterator::~NativeIterator()
+{
+}
+
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
+}
+
+
+//==============================================================================
+bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters)
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ NSURL* filenameAsURL = [NSURL URLWithString: juceStringToNS (fileName)];
+
+ #if JUCE_IOS
+ (void) parameters;
+ return [[UIApplication sharedApplication] openURL: filenameAsURL];
+ #else
+ NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
+
+ if (parameters.isEmpty())
+ return [workspace openFile: juceStringToNS (fileName)]
+ || [workspace openURL: filenameAsURL];
+
+ const File file (fileName);
+
+ if (file.isBundle())
+ {
+ StringArray params;
+ params.addTokens (parameters, true);
+
+ NSMutableArray* paramArray = [[[NSMutableArray alloc] init] autorelease];
+ for (int i = 0; i < params.size(); ++i)
+ [paramArray addObject: juceStringToNS (params[i])];
+
+ NSMutableDictionary* dict = [[[NSMutableDictionary alloc] init] autorelease];
+ [dict setObject: paramArray
+ forKey: nsStringLiteral ("NSWorkspaceLaunchConfigurationArguments")];
+
+ return [workspace launchApplicationAtURL: filenameAsURL
+ options: NSWorkspaceLaunchDefault | NSWorkspaceLaunchNewInstance
+ configuration: dict
+ error: nil];
+ }
+
+ if (file.exists())
+ return FileHelpers::launchExecutable ("\"" + fileName + "\" " + parameters);
+
+ return false;
+ #endif
+ }
+}
+
+void File::revealToUser() const
+{
+ #if ! JUCE_IOS
+ if (exists())
+ [[NSWorkspace sharedWorkspace] selectFile: juceStringToNS (getFullPathName()) inFileViewerRootedAtPath: nsEmptyString()];
+ else if (getParentDirectory().exists())
+ getParentDirectory().revealToUser();
+ #endif
+}
+
+//==============================================================================
+OSType File::getMacOSType() const
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ #if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+ NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: juceStringToNS (getFullPathName()) error: nil];
+ #else
+ // (the cast here avoids a deprecation warning)
+ NSDictionary* fileDict = [((id) [NSFileManager defaultManager]) fileAttributesAtPath: juceStringToNS (getFullPathName()) traverseLink: NO];
+ #endif
+
+ return [fileDict fileHFSTypeCode];
+ }
+}
+
+bool File::isBundle() const
+{
+ #if JUCE_IOS
+ return false; // xxx can't find a sensible way to do this without trying to open the bundle..
+ #else
+ JUCE_AUTORELEASEPOOL
+ {
+ return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (getFullPathName())];
+ }
+ #endif
+}
+
+#if JUCE_MAC
+void File::addToDock() const
+{
+ // check that it's not already there...
+ if (! juce_getOutputFromCommand ("defaults read com.apple.dock persistent-apps").containsIgnoreCase (getFullPathName()))
+ {
+ juce_runSystemCommand ("defaults write com.apple.dock persistent-apps -array-add \"<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>"
+ + getFullPathName() + "</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>\"");
+
+ juce_runSystemCommand ("osascript -e \"tell application \\\"Dock\\\" to quit\"");
+ }
+}
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Network.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Network.mm
new file mode 100644
index 0000000..130759e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Network.mm
@@ -0,0 +1,445 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+void MACAddress::findAllAddresses (Array<MACAddress>& result)
+{
+ ifaddrs* addrs = nullptr;
+
+ if (getifaddrs (&addrs) == 0)
+ {
+ for (const ifaddrs* cursor = addrs; cursor != nullptr; cursor = cursor->ifa_next)
+ {
+ sockaddr_storage* sto = (sockaddr_storage*) cursor->ifa_addr;
+ if (sto->ss_family == AF_LINK)
+ {
+ const sockaddr_dl* const sadd = (const sockaddr_dl*) cursor->ifa_addr;
+
+ #ifndef IFT_ETHER
+ enum { IFT_ETHER = 6 };
+ #endif
+
+ if (sadd->sdl_type == IFT_ETHER)
+ {
+ MACAddress ma (MACAddress (((const uint8*) sadd->sdl_data) + sadd->sdl_nlen));
+
+ if (! ma.isNull())
+ result.addIfNotAlreadyThere (ma);
+ }
+ }
+ }
+
+ freeifaddrs (addrs);
+ }
+}
+
+//==============================================================================
+bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailAddress,
+ const String& emailSubject,
+ const String& bodyText,
+ const StringArray& filesToAttach)
+{
+ #if JUCE_IOS
+ (void) targetEmailAddress;
+ (void) emailSubject;
+ (void) bodyText;
+ (void) filesToAttach;
+
+ //xxx probably need to use MFMailComposeViewController
+ jassertfalse;
+ return false;
+ #else
+ JUCE_AUTORELEASEPOOL
+ {
+ String script;
+ script << "tell application \"Mail\"\r\n"
+ "set newMessage to make new outgoing message with properties {subject:\""
+ << emailSubject.replace ("\"", "\\\"")
+ << "\", content:\""
+ << bodyText.replace ("\"", "\\\"")
+ << "\" & return & return}\r\n"
+ "tell newMessage\r\n"
+ "set visible to true\r\n"
+ "set sender to \"sdfsdfsdfewf\"\r\n"
+ "make new to recipient at end of to recipients with properties {address:\""
+ << targetEmailAddress
+ << "\"}\r\n";
+
+ for (int i = 0; i < filesToAttach.size(); ++i)
+ {
+ script << "tell content\r\n"
+ "make new attachment with properties {file name:\""
+ << filesToAttach[i].replace ("\"", "\\\"")
+ << "\"} at after the last paragraph\r\n"
+ "end tell\r\n";
+ }
+
+ script << "end tell\r\n"
+ "end tell\r\n";
+
+ NSAppleScript* s = [[NSAppleScript alloc] initWithSource: juceStringToNS (script)];
+ NSDictionary* error = nil;
+ const bool ok = [s executeAndReturnError: &error] != nil;
+ [s release];
+
+ return ok;
+ }
+ #endif
+}
+
+//==============================================================================
+class URLConnectionState : public Thread
+{
+public:
+ URLConnectionState (NSURLRequest* req)
+ : Thread ("http connection"),
+ contentLength (-1),
+ delegate (nil),
+ request ([req retain]),
+ connection (nil),
+ data ([[NSMutableData data] retain]),
+ headers (nil),
+ statusCode (0),
+ initialised (false),
+ hasFailed (false),
+ hasFinished (false)
+ {
+ static DelegateClass cls;
+ delegate = [cls.createInstance() init];
+ DelegateClass::setState (delegate, this);
+ }
+
+ ~URLConnectionState()
+ {
+ stop();
+ [connection release];
+ [data release];
+ [request release];
+ [headers release];
+ [delegate release];
+ }
+
+ bool start (URL::OpenStreamProgressCallback* callback, void* context)
+ {
+ startThread();
+
+ while (isThreadRunning() && ! initialised)
+ {
+ if (callback != nullptr)
+ callback (context, -1, (int) [[request HTTPBody] length]);
+
+ Thread::sleep (1);
+ }
+
+ return connection != nil && ! hasFailed;
+ }
+
+ void stop()
+ {
+ [connection cancel];
+ stopThread (10000);
+ }
+
+ int read (char* dest, int numBytes)
+ {
+ int numDone = 0;
+
+ while (numBytes > 0)
+ {
+ const int available = jmin (numBytes, (int) [data length]);
+
+ if (available > 0)
+ {
+ const ScopedLock sl (dataLock);
+ [data getBytes: dest length: (NSUInteger) available];
+ [data replaceBytesInRange: NSMakeRange (0, (NSUInteger) available) withBytes: nil length: 0];
+
+ numDone += available;
+ numBytes -= available;
+ dest += available;
+ }
+ else
+ {
+ if (hasFailed || hasFinished)
+ break;
+
+ Thread::sleep (1);
+ }
+ }
+
+ return numDone;
+ }
+
+ void didReceiveResponse (NSURLResponse* response)
+ {
+ {
+ const ScopedLock sl (dataLock);
+ [data setLength: 0];
+ }
+
+ initialised = true;
+ contentLength = [response expectedContentLength];
+
+ [headers release];
+ headers = nil;
+
+ if ([response isKindOfClass: [NSHTTPURLResponse class]])
+ {
+ NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
+ headers = [[httpResponse allHeaderFields] retain];
+ statusCode = (int) [httpResponse statusCode];
+ }
+ }
+
+ void didFailWithError (NSError* error)
+ {
+ DBG (nsStringToJuce ([error description])); (void) error;
+ hasFailed = true;
+ initialised = true;
+ signalThreadShouldExit();
+ }
+
+ void didReceiveData (NSData* newData)
+ {
+ const ScopedLock sl (dataLock);
+ [data appendData: newData];
+ initialised = true;
+ }
+
+ void didSendBodyData (NSInteger /*totalBytesWritten*/, NSInteger /*totalBytesExpected*/)
+ {
+ }
+
+ void finishedLoading()
+ {
+ hasFinished = true;
+ initialised = true;
+ signalThreadShouldExit();
+ }
+
+ void run() override
+ {
+ connection = [[NSURLConnection alloc] initWithRequest: request
+ delegate: delegate];
+ while (! threadShouldExit())
+ {
+ JUCE_AUTORELEASEPOOL
+ {
+ [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
+ }
+ }
+ }
+
+ int64 contentLength;
+ CriticalSection dataLock;
+ NSObject* delegate;
+ NSURLRequest* request;
+ NSURLConnection* connection;
+ NSMutableData* data;
+ NSDictionary* headers;
+ int statusCode;
+ bool initialised, hasFailed, hasFinished;
+
+private:
+ //==============================================================================
+ struct DelegateClass : public ObjCClass<NSObject>
+ {
+ DelegateClass() : ObjCClass<NSObject> ("JUCEAppDelegate_")
+ {
+ addIvar<URLConnectionState*> ("state");
+
+ addMethod (@selector (connection:didReceiveResponse:), didReceiveResponse, "v@:@@");
+ addMethod (@selector (connection:didFailWithError:), didFailWithError, "v@:@@");
+ addMethod (@selector (connection:didReceiveData:), didReceiveData, "v@:@@");
+ addMethod (@selector (connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:),
+ connectionDidSendBodyData, "v@:@iii");
+ addMethod (@selector (connectionDidFinishLoading:), connectionDidFinishLoading, "v@:@");
+ addMethod (@selector (connection:willSendRequest:redirectResponse:), willSendRequest, "@@:@@");
+
+ registerClass();
+ }
+
+ static void setState (id self, URLConnectionState* state) { object_setInstanceVariable (self, "state", state); }
+ static URLConnectionState* getState (id self) { return getIvar<URLConnectionState*> (self, "state"); }
+
+ private:
+ static void didReceiveResponse (id self, SEL, NSURLConnection*, NSURLResponse* response)
+ {
+ getState (self)->didReceiveResponse (response);
+ }
+
+ static void didFailWithError (id self, SEL, NSURLConnection*, NSError* error)
+ {
+ getState (self)->didFailWithError (error);
+ }
+
+ static void didReceiveData (id self, SEL, NSURLConnection*, NSData* newData)
+ {
+ getState (self)->didReceiveData (newData);
+ }
+
+ static NSURLRequest* willSendRequest (id, SEL, NSURLConnection*, NSURLRequest* request, NSURLResponse*)
+ {
+ return request;
+ }
+
+ static void connectionDidSendBodyData (id self, SEL, NSURLConnection*, NSInteger, NSInteger totalBytesWritten, NSInteger totalBytesExpected)
+ {
+ getState (self)->didSendBodyData (totalBytesWritten, totalBytesExpected);
+ }
+
+ static void connectionDidFinishLoading (id self, SEL, NSURLConnection*)
+ {
+ getState (self)->finishedLoading();
+ }
+ };
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLConnectionState)
+};
+
+
+//==============================================================================
+class WebInputStream : public InputStream
+{
+public:
+ WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
+ : statusCode (0), address (address_), headers (headers_), postData (postData_), position (0),
+ finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
+ {
+ JUCE_AUTORELEASEPOOL
+ {
+ createConnection (progressCallback, progressCallbackContext);
+
+ if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil)
+ {
+ statusCode = connection->statusCode;
+
+ NSEnumerator* enumerator = [connection->headers keyEnumerator];
+
+ while (NSString* key = [enumerator nextObject])
+ responseHeaders->set (nsStringToJuce (key),
+ nsStringToJuce ((NSString*) [connection->headers objectForKey: key]));
+ }
+ }
+ }
+
+ //==============================================================================
+ bool isError() const { return connection == nullptr; }
+ int64 getTotalLength() override { return connection == nullptr ? -1 : connection->contentLength; }
+ bool isExhausted() override { return finished; }
+ int64 getPosition() override { return position; }
+
+ int read (void* buffer, int bytesToRead) override
+ {
+ jassert (buffer != nullptr && bytesToRead >= 0);
+
+ if (finished || isError())
+ return 0;
+
+ JUCE_AUTORELEASEPOOL
+ {
+ const int bytesRead = connection->read (static_cast<char*> (buffer), bytesToRead);
+ position += bytesRead;
+
+ if (bytesRead == 0)
+ finished = true;
+
+ return bytesRead;
+ }
+ }
+
+ bool setPosition (int64 wantedPos) override
+ {
+ if (wantedPos != position)
+ {
+ finished = false;
+
+ if (wantedPos < position)
+ {
+ connection = nullptr;
+ position = 0;
+ createConnection (0, 0);
+ }
+
+ skipNextBytes (wantedPos - position);
+ }
+
+ return true;
+ }
+
+ int statusCode;
+
+private:
+ ScopedPointer<URLConnectionState> connection;
+ String address, headers;
+ MemoryBlock postData;
+ int64 position;
+ bool finished;
+ const bool isPost;
+ const int timeOutMs;
+
+ void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
+ {
+ jassert (connection == nullptr);
+
+ NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (address)]
+ cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
+ timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)];
+
+ if (req != nil)
+ {
+ [req setHTTPMethod: nsStringLiteral (isPost ? "POST" : "GET")];
+ //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
+
+ StringArray headerLines;
+ headerLines.addLines (headers);
+ headerLines.removeEmptyStrings (true);
+
+ for (int i = 0; i < headerLines.size(); ++i)
+ {
+ const String key (headerLines[i].upToFirstOccurrenceOf (":", false, false).trim());
+ const String value (headerLines[i].fromFirstOccurrenceOf (":", false, false).trim());
+
+ if (key.isNotEmpty() && value.isNotEmpty())
+ [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
+ }
+
+ if (isPost && postData.getSize() > 0)
+ [req setHTTPBody: [NSData dataWithBytes: postData.getData()
+ length: postData.getSize()]];
+
+ connection = new URLConnectionState (req);
+
+ if (! connection->start (progressCallback, progressCallbackContext))
+ connection = nullptr;
+ }
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Strings.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Strings.mm
new file mode 100644
index 0000000..862eb53
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Strings.mm
@@ -0,0 +1,96 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+String String::fromCFString (CFStringRef cfString)
+{
+ if (cfString == 0)
+ return String();
+
+ CFRange range = { 0, CFStringGetLength (cfString) };
+ HeapBlock <UniChar> u ((size_t) range.length + 1);
+ CFStringGetCharacters (cfString, range, u);
+ u[range.length] = 0;
+
+ return String (CharPointer_UTF16 ((const CharPointer_UTF16::CharType*) u.getData()));
+}
+
+CFStringRef String::toCFString() const
+{
+ CharPointer_UTF16 utf16 (toUTF16());
+ return CFStringCreateWithCharacters (kCFAllocatorDefault, (const UniChar*) utf16.getAddress(), (CFIndex) utf16.length());
+}
+
+String String::convertToPrecomposedUnicode() const
+{
+ #if JUCE_IOS
+ JUCE_AUTORELEASEPOOL
+ {
+ return nsStringToJuce ([juceStringToNS (*this) precomposedStringWithCanonicalMapping]);
+ }
+ #else
+ UnicodeMapping map;
+
+ map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
+ kUnicodeNoSubset,
+ kTextEncodingDefaultFormat);
+
+ map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
+ kUnicodeCanonicalCompVariant,
+ kTextEncodingDefaultFormat);
+
+ map.mappingVersion = kUnicodeUseLatestMapping;
+
+ UnicodeToTextInfo conversionInfo = 0;
+ String result;
+
+ if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr)
+ {
+ const size_t bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (getCharPointer());
+
+ HeapBlock <char> tempOut;
+ tempOut.calloc (bytesNeeded + 4);
+
+ ByteCount bytesRead = 0;
+ ByteCount outputBufferSize = 0;
+
+ if (ConvertFromUnicodeToText (conversionInfo,
+ bytesNeeded, (ConstUniCharArrayPtr) toUTF16().getAddress(),
+ kUnicodeDefaultDirectionMask,
+ 0, 0, 0, 0,
+ bytesNeeded, &bytesRead,
+ &outputBufferSize, tempOut) == noErr)
+ {
+ result = String (CharPointer_UTF16 ((CharPointer_UTF16::CharType*) tempOut.getData()));
+ }
+
+ DisposeUnicodeToTextInfo (&conversionInfo);
+ }
+
+ return result;
+ #endif
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_SystemStats.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_SystemStats.mm
new file mode 100644
index 0000000..2d49ae6
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_SystemStats.mm
@@ -0,0 +1,306 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+ScopedAutoReleasePool::ScopedAutoReleasePool()
+{
+ pool = [[NSAutoreleasePool alloc] init];
+}
+
+ScopedAutoReleasePool::~ScopedAutoReleasePool()
+{
+ [((NSAutoreleasePool*) pool) release];
+}
+
+//==============================================================================
+void Logger::outputDebugString (const String& text)
+{
+ // Would prefer to use std::cerr here, but avoiding it for
+ // the moment, due to clang JIT linkage problems.
+ fputs (text.toRawUTF8(), stderr);
+ fputs ("\n", stderr);
+ fflush (stderr);
+}
+
+//==============================================================================
+namespace SystemStatsHelpers
+{
+ #if JUCE_INTEL && ! JUCE_NO_INLINE_ASM
+ static void doCPUID (uint32& a, uint32& b, uint32& c, uint32& d, uint32 type)
+ {
+ uint32 la = a, lb = b, lc = c, ld = d;
+
+ asm ("mov %%ebx, %%esi \n\t"
+ "cpuid \n\t"
+ "xchg %%esi, %%ebx"
+ : "=a" (la), "=S" (lb), "=c" (lc), "=d" (ld) : "a" (type)
+ #if JUCE_64BIT
+ , "b" (lb), "c" (lc), "d" (ld)
+ #endif
+ );
+
+ a = la; b = lb; c = lc; d = ld;
+ }
+ #endif
+}
+
+//==============================================================================
+void CPUInformation::initialise() noexcept
+{
+ #if JUCE_INTEL && ! JUCE_NO_INLINE_ASM
+ uint32 a = 0, b = 0, d = 0, c = 0;
+ SystemStatsHelpers::doCPUID (a, b, c, d, 1);
+
+ hasMMX = (d & (1u << 23)) != 0;
+ hasSSE = (d & (1u << 25)) != 0;
+ hasSSE2 = (d & (1u << 26)) != 0;
+ has3DNow = (b & (1u << 31)) != 0;
+ hasSSE3 = (c & (1u << 0)) != 0;
+ #endif
+
+ #if JUCE_IOS || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+ numCpus = (int) [[NSProcessInfo processInfo] activeProcessorCount];
+ #else
+ numCpus = (int) MPProcessors();
+ #endif
+}
+
+#if JUCE_MAC
+struct RLimitInitialiser
+{
+ RLimitInitialiser()
+ {
+ rlimit lim;
+ getrlimit (RLIMIT_NOFILE, &lim);
+ lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_NOFILE, &lim);
+ }
+};
+
+static RLimitInitialiser rLimitInitialiser;
+#endif
+
+//==============================================================================
+#if ! JUCE_IOS
+static String getOSXVersion()
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:
+ nsStringLiteral ("/System/Library/CoreServices/SystemVersion.plist")];
+
+ return nsStringToJuce ([dict objectForKey: nsStringLiteral ("ProductVersion")]);
+ }
+}
+#endif
+
+SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
+{
+ #if JUCE_IOS
+ return iOS;
+ #else
+ StringArray parts;
+ parts.addTokens (getOSXVersion(), ".", StringRef());
+
+ jassert (parts[0].getIntValue() == 10);
+ const int major = parts[1].getIntValue();
+ jassert (major > 2);
+
+ return (OperatingSystemType) (major + MacOSX_10_4 - 4);
+ #endif
+}
+
+String SystemStats::getOperatingSystemName()
+{
+ #if JUCE_IOS
+ return "iOS " + nsStringToJuce ([[UIDevice currentDevice] systemVersion]);
+ #else
+ return "Mac OSX " + getOSXVersion();
+ #endif
+}
+
+String SystemStats::getDeviceDescription()
+{
+ #if JUCE_IOS
+ return nsStringToJuce ([[UIDevice currentDevice] model]);
+ #else
+ return String();
+ #endif
+}
+
+bool SystemStats::isOperatingSystem64Bit()
+{
+ #if JUCE_IOS
+ return false;
+ #elif JUCE_64BIT
+ return true;
+ #else
+ return getOperatingSystemType() >= MacOSX_10_6;
+ #endif
+}
+
+int SystemStats::getMemorySizeInMegabytes()
+{
+ uint64 mem = 0;
+ size_t memSize = sizeof (mem);
+ int mib[] = { CTL_HW, HW_MEMSIZE };
+ sysctl (mib, 2, &mem, &memSize, 0, 0);
+ return (int) (mem / (1024 * 1024));
+}
+
+String SystemStats::getCpuVendor()
+{
+ #if JUCE_INTEL && ! JUCE_NO_INLINE_ASM
+ uint32 dummy = 0;
+ uint32 vendor[4] = { 0 };
+
+ SystemStatsHelpers::doCPUID (dummy, vendor[0], vendor[2], vendor[1], 0);
+
+ return String (reinterpret_cast <const char*> (vendor), 12);
+ #else
+ return String();
+ #endif
+}
+
+int SystemStats::getCpuSpeedInMegaherz()
+{
+ uint64 speedHz = 0;
+ size_t speedSize = sizeof (speedHz);
+ int mib[] = { CTL_HW, HW_CPU_FREQ };
+ sysctl (mib, 2, &speedHz, &speedSize, 0, 0);
+
+ #if JUCE_BIG_ENDIAN
+ if (speedSize == 4)
+ speedHz >>= 32;
+ #endif
+
+ return (int) (speedHz / 1000000);
+}
+
+//==============================================================================
+String SystemStats::getLogonName()
+{
+ return nsStringToJuce (NSUserName());
+}
+
+String SystemStats::getFullUserName()
+{
+ return nsStringToJuce (NSFullUserName());
+}
+
+String SystemStats::getComputerName()
+{
+ char name [256] = { 0 };
+ if (gethostname (name, sizeof (name) - 1) == 0)
+ return String (name).upToLastOccurrenceOf (".local", false, true);
+
+ return String();
+}
+
+static String getLocaleValue (CFStringRef key)
+{
+ CFLocaleRef cfLocale = CFLocaleCopyCurrent();
+ const String result (String::fromCFString ((CFStringRef) CFLocaleGetValue (cfLocale, key)));
+ CFRelease (cfLocale);
+ return result;
+}
+
+String SystemStats::getUserLanguage() { return getLocaleValue (kCFLocaleLanguageCode); }
+String SystemStats::getUserRegion() { return getLocaleValue (kCFLocaleCountryCode); }
+
+String SystemStats::getDisplayLanguage()
+{
+ CFArrayRef cfPrefLangs = CFLocaleCopyPreferredLanguages();
+ const String result (String::fromCFString ((CFStringRef) CFArrayGetValueAtIndex (cfPrefLangs, 0)));
+ CFRelease (cfPrefLangs);
+ return result;
+}
+
+//==============================================================================
+/* NB: these are kept outside the HiResCounterInfo struct and initialised to 1 to avoid
+ division-by-zero errors if some other static constructor calls us before this file's
+ static constructors have had a chance to fill them in correctly..
+*/
+static uint64 hiResCounterNumerator = 0, hiResCounterDenominator = 1;
+
+class HiResCounterInfo
+{
+public:
+ HiResCounterInfo()
+ {
+ mach_timebase_info_data_t timebase;
+ (void) mach_timebase_info (&timebase);
+
+ if (timebase.numer % 1000000 == 0)
+ {
+ hiResCounterNumerator = timebase.numer / 1000000;
+ hiResCounterDenominator = timebase.denom;
+ }
+ else
+ {
+ hiResCounterNumerator = timebase.numer;
+ hiResCounterDenominator = timebase.denom * (uint64) 1000000;
+ }
+
+ highResTimerFrequency = (timebase.denom * (uint64) 1000000000) / timebase.numer;
+ highResTimerToMillisecRatio = hiResCounterNumerator / (double) hiResCounterDenominator;
+ }
+
+ uint32 millisecondsSinceStartup() const noexcept
+ {
+ return (uint32) ((mach_absolute_time() * hiResCounterNumerator) / hiResCounterDenominator);
+ }
+
+ double getMillisecondCounterHiRes() const noexcept
+ {
+ return mach_absolute_time() * highResTimerToMillisecRatio;
+ }
+
+ int64 highResTimerFrequency;
+
+private:
+ double highResTimerToMillisecRatio;
+};
+
+static HiResCounterInfo hiResCounterInfo;
+
+uint32 juce_millisecondsSinceStartup() noexcept { return hiResCounterInfo.millisecondsSinceStartup(); }
+double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterInfo.getMillisecondCounterHiRes(); }
+int64 Time::getHighResolutionTicksPerSecond() noexcept { return hiResCounterInfo.highResTimerFrequency; }
+int64 Time::getHighResolutionTicks() noexcept { return (int64) mach_absolute_time(); }
+
+bool Time::setSystemTimeToThisTime() const
+{
+ jassertfalse;
+ return false;
+}
+
+//==============================================================================
+int SystemStats::getPageSize()
+{
+ return (int) NSPageSize();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Threads.mm b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Threads.mm
new file mode 100644
index 0000000..004baeb
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_mac_Threads.mm
@@ -0,0 +1,97 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+/*
+ Note that a lot of methods that you'd expect to find in this file actually
+ live in juce_posix_SharedCode.h!
+*/
+
+#if JUCE_IOS
+bool isIOSAppActive = true;
+#endif
+
+//==============================================================================
+JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess()
+{
+ #if JUCE_MAC
+ return [NSApp isActive];
+ #else
+ return isIOSAppActive;
+ #endif
+}
+
+JUCE_API void JUCE_CALLTYPE Process::makeForegroundProcess()
+{
+ #if JUCE_MAC
+ [NSApp activateIgnoringOtherApps: YES];
+ #endif
+}
+
+JUCE_API void JUCE_CALLTYPE Process::hide()
+{
+ #if JUCE_MAC
+ [NSApp hide: nil];
+ #endif
+}
+
+JUCE_API void JUCE_CALLTYPE Process::raisePrivilege()
+{
+ jassertfalse;
+}
+
+JUCE_API void JUCE_CALLTYPE Process::lowerPrivilege()
+{
+ jassertfalse;
+}
+
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority)
+{
+ // xxx
+}
+
+//==============================================================================
+JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger()
+{
+ static char testResult = 0;
+
+ if (testResult == 0)
+ {
+ struct kinfo_proc info;
+ int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
+ size_t sz = sizeof (info);
+ sysctl (m, 4, &info, &sz, 0, 0);
+ testResult = ((info.kp_proc.p_flag & P_TRACED) != 0) ? 1 : -1;
+ }
+
+ return testResult > 0;
+}
+
+JUCE_API bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
+{
+ return juce_isRunningUnderDebugger();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_osx_ObjCHelpers.h b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_osx_ObjCHelpers.h
new file mode 100644
index 0000000..10878d0
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_osx_ObjCHelpers.h
@@ -0,0 +1,169 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_OSX_OBJCHELPERS_H_INCLUDED
+#define JUCE_OSX_OBJCHELPERS_H_INCLUDED
+
+
+/* This file contains a few helper functions that are used internally but which
+ need to be kept away from the public headers because they use obj-C symbols.
+*/
+namespace
+{
+ //==============================================================================
+ static inline String nsStringToJuce (NSString* s)
+ {
+ return CharPointer_UTF8 ([s UTF8String]);
+ }
+
+ static inline NSString* juceStringToNS (const String& s)
+ {
+ return [NSString stringWithUTF8String: s.toUTF8()];
+ }
+
+ static inline NSString* nsStringLiteral (const char* const s) noexcept
+ {
+ return [NSString stringWithUTF8String: s];
+ }
+
+ static inline NSString* nsEmptyString() noexcept
+ {
+ return [NSString string];
+ }
+
+ #if JUCE_MAC
+ template <typename RectangleType>
+ static NSRect makeNSRect (const RectangleType& r) noexcept
+ {
+ return NSMakeRect (static_cast <CGFloat> (r.getX()),
+ static_cast <CGFloat> (r.getY()),
+ static_cast <CGFloat> (r.getWidth()),
+ static_cast <CGFloat> (r.getHeight()));
+ }
+ #endif
+}
+
+//==============================================================================
+template <typename ObjectType>
+struct NSObjectRetainer
+{
+ inline NSObjectRetainer (ObjectType* o) : object (o) { [object retain]; }
+ inline ~NSObjectRetainer() { [object release]; }
+
+ ObjectType* object;
+};
+
+//==============================================================================
+template <typename SuperclassType>
+struct ObjCClass
+{
+ ObjCClass (const char* nameRoot)
+ : cls (objc_allocateClassPair ([SuperclassType class], getRandomisedName (nameRoot).toUTF8(), 0))
+ {
+ }
+
+ ~ObjCClass()
+ {
+ objc_disposeClassPair (cls);
+ }
+
+ void registerClass()
+ {
+ objc_registerClassPair (cls);
+ }
+
+ SuperclassType* createInstance() const
+ {
+ return class_createInstance (cls, 0);
+ }
+
+ template <typename Type>
+ void addIvar (const char* name)
+ {
+ BOOL b = class_addIvar (cls, name, sizeof (Type), (uint8_t) rint (log2 (sizeof (Type))), @encode (Type));
+ jassert (b); (void) b;
+ }
+
+ template <typename FunctionType>
+ void addMethod (SEL selector, FunctionType callbackFn, const char* signature)
+ {
+ BOOL b = class_addMethod (cls, selector, (IMP) callbackFn, signature);
+ jassert (b); (void) b;
+ }
+
+ template <typename FunctionType>
+ void addMethod (SEL selector, FunctionType callbackFn, const char* sig1, const char* sig2)
+ {
+ addMethod (selector, callbackFn, (String (sig1) + sig2).toUTF8());
+ }
+
+ template <typename FunctionType>
+ void addMethod (SEL selector, FunctionType callbackFn, const char* sig1, const char* sig2, const char* sig3)
+ {
+ addMethod (selector, callbackFn, (String (sig1) + sig2 + sig3).toUTF8());
+ }
+
+ template <typename FunctionType>
+ void addMethod (SEL selector, FunctionType callbackFn, const char* sig1, const char* sig2, const char* sig3, const char* sig4)
+ {
+ addMethod (selector, callbackFn, (String (sig1) + sig2 + sig3 + sig4).toUTF8());
+ }
+
+ void addProtocol (Protocol* protocol)
+ {
+ BOOL b = class_addProtocol (cls, protocol);
+ jassert (b); (void) b;
+ }
+
+ static id sendSuperclassMessage (id self, SEL selector)
+ {
+ objc_super s = { self, [SuperclassType class] };
+ return objc_msgSendSuper (&s, selector);
+ }
+
+ template <typename Type>
+ static Type getIvar (id self, const char* name)
+ {
+ void* v = nullptr;
+ object_getInstanceVariable (self, name, &v);
+ return static_cast <Type> (v);
+ }
+
+ Class cls;
+
+private:
+ static String getRandomisedName (const char* root)
+ {
+ return root + String::toHexString (juce::Random::getSystemRandom().nextInt64());
+ }
+
+ JUCE_DECLARE_NON_COPYABLE (ObjCClass)
+};
+
+
+#endif // JUCE_OSX_OBJCHELPERS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_NamedPipe.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_NamedPipe.cpp
new file mode 100644
index 0000000..d0c0b09
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_NamedPipe.cpp
@@ -0,0 +1,224 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class NamedPipe::Pimpl
+{
+public:
+ Pimpl (const String& pipePath, bool createPipe)
+ : pipeInName (pipePath + "_in"),
+ pipeOutName (pipePath + "_out"),
+ pipeIn (-1), pipeOut (-1),
+ createdPipe (createPipe),
+ stopReadOperation (false)
+ {
+ signal (SIGPIPE, signalHandler);
+ juce_siginterrupt (SIGPIPE, 1);
+ }
+
+ ~Pimpl()
+ {
+ if (pipeIn != -1) ::close (pipeIn);
+ if (pipeOut != -1) ::close (pipeOut);
+
+ if (createdPipe)
+ {
+ unlink (pipeInName.toUTF8());
+ unlink (pipeOutName.toUTF8());
+ }
+ }
+
+ int read (char* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
+ {
+ const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
+
+ if (pipeIn == -1)
+ {
+ pipeIn = openPipe (createdPipe ? pipeInName : pipeOutName, O_RDWR | O_NONBLOCK, timeoutEnd);
+
+ if (pipeIn == -1)
+ return -1;
+ }
+
+ int bytesRead = 0;
+
+ while (bytesRead < maxBytesToRead)
+ {
+ const int bytesThisTime = maxBytesToRead - bytesRead;
+ const int numRead = (int) ::read (pipeIn, destBuffer, (size_t) bytesThisTime);
+
+ if (numRead <= 0)
+ {
+ if (errno != EWOULDBLOCK || stopReadOperation || hasExpired (timeoutEnd))
+ return -1;
+
+ const int maxWaitingTime = 30;
+ waitForInput (pipeIn, timeoutEnd == 0 ? maxWaitingTime
+ : jmin (maxWaitingTime,
+ (int) (timeoutEnd - Time::getMillisecondCounter())));
+ continue;
+ }
+
+ bytesRead += numRead;
+ destBuffer += numRead;
+ }
+
+ return bytesRead;
+ }
+
+ int write (const char* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
+ {
+ const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
+
+ if (pipeOut == -1)
+ {
+ pipeOut = openPipe (createdPipe ? pipeOutName : pipeInName, O_WRONLY, timeoutEnd);
+
+ if (pipeOut == -1)
+ return -1;
+ }
+
+ int bytesWritten = 0;
+
+ while (bytesWritten < numBytesToWrite && ! hasExpired (timeoutEnd))
+ {
+ const int bytesThisTime = numBytesToWrite - bytesWritten;
+ const int numWritten = (int) ::write (pipeOut, sourceBuffer, (size_t) bytesThisTime);
+
+ if (numWritten <= 0)
+ return -1;
+
+ bytesWritten += numWritten;
+ sourceBuffer += numWritten;
+ }
+
+ return bytesWritten;
+ }
+
+ bool createFifos() const
+ {
+ return (mkfifo (pipeInName .toUTF8(), 0666) == 0 || errno == EEXIST)
+ && (mkfifo (pipeOutName.toUTF8(), 0666) == 0 || errno == EEXIST);
+ }
+
+ const String pipeInName, pipeOutName;
+ int pipeIn, pipeOut;
+
+ const bool createdPipe;
+ bool stopReadOperation;
+
+private:
+ static void signalHandler (int) {}
+
+ static uint32 getTimeoutEnd (const int timeOutMilliseconds)
+ {
+ return timeOutMilliseconds >= 0 ? Time::getMillisecondCounter() + (uint32) timeOutMilliseconds : 0;
+ }
+
+ static bool hasExpired (const uint32 timeoutEnd)
+ {
+ return timeoutEnd != 0 && Time::getMillisecondCounter() >= timeoutEnd;
+ }
+
+ int openPipe (const String& name, int flags, const uint32 timeoutEnd)
+ {
+ for (;;)
+ {
+ const int p = ::open (name.toUTF8(), flags);
+
+ if (p != -1 || hasExpired (timeoutEnd) || stopReadOperation)
+ return p;
+
+ Thread::sleep (2);
+ }
+ }
+
+ static void waitForInput (const int handle, const int timeoutMsecs) noexcept
+ {
+ struct timeval timeout;
+ timeout.tv_sec = timeoutMsecs / 1000;
+ timeout.tv_usec = (timeoutMsecs % 1000) * 1000;
+
+ fd_set rset;
+ FD_ZERO (&rset);
+ FD_SET (handle, &rset);
+
+ select (handle + 1, &rset, nullptr, 0, &timeout);
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
+};
+
+void NamedPipe::close()
+{
+ if (pimpl != nullptr)
+ {
+ pimpl->stopReadOperation = true;
+
+ char buffer[1] = { 0 };
+ ssize_t done = ::write (pimpl->pipeIn, buffer, 1);
+ (void) done;
+
+ ScopedWriteLock sl (lock);
+ pimpl = nullptr;
+ }
+}
+
+bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
+{
+ #if JUCE_IOS
+ pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory)
+ .getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe);
+ #else
+ String file (pipeName);
+
+ if (! File::isAbsolutePath (file))
+ file = "/tmp/" + File::createLegalFileName (file);
+
+ pimpl = new Pimpl (file, createPipe);
+ #endif
+
+ if (createPipe && ! pimpl->createFifos())
+ {
+ pimpl = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
+{
+ ScopedReadLock sl (lock);
+ return pimpl != nullptr ? pimpl->read (static_cast <char*> (destBuffer), maxBytesToRead, timeOutMilliseconds) : -1;
+}
+
+int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
+{
+ ScopedReadLock sl (lock);
+ return pimpl != nullptr ? pimpl->write (static_cast <const char*> (sourceBuffer), numBytesToWrite, timeOutMilliseconds) : -1;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_SharedCode.h b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_SharedCode.h
new file mode 100644
index 0000000..2636cea
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_posix_SharedCode.h
@@ -0,0 +1,1301 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+CriticalSection::CriticalSection() noexcept
+{
+ pthread_mutexattr_t atts;
+ pthread_mutexattr_init (&atts);
+ pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE);
+ #if ! JUCE_ANDROID
+ pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
+ #endif
+ pthread_mutex_init (&lock, &atts);
+ pthread_mutexattr_destroy (&atts);
+}
+
+CriticalSection::~CriticalSection() noexcept { pthread_mutex_destroy (&lock); }
+void CriticalSection::enter() const noexcept { pthread_mutex_lock (&lock); }
+bool CriticalSection::tryEnter() const noexcept { return pthread_mutex_trylock (&lock) == 0; }
+void CriticalSection::exit() const noexcept { pthread_mutex_unlock (&lock); }
+
+//==============================================================================
+WaitableEvent::WaitableEvent (const bool useManualReset) noexcept
+ : triggered (false), manualReset (useManualReset)
+{
+ pthread_cond_init (&condition, 0);
+
+ pthread_mutexattr_t atts;
+ pthread_mutexattr_init (&atts);
+ #if ! JUCE_ANDROID
+ pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
+ #endif
+ pthread_mutex_init (&mutex, &atts);
+}
+
+WaitableEvent::~WaitableEvent() noexcept
+{
+ pthread_cond_destroy (&condition);
+ pthread_mutex_destroy (&mutex);
+}
+
+bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept
+{
+ pthread_mutex_lock (&mutex);
+
+ if (! triggered)
+ {
+ if (timeOutMillisecs < 0)
+ {
+ do
+ {
+ pthread_cond_wait (&condition, &mutex);
+ }
+ while (! triggered);
+ }
+ else
+ {
+ struct timeval now;
+ gettimeofday (&now, 0);
+
+ struct timespec time;
+ time.tv_sec = now.tv_sec + (timeOutMillisecs / 1000);
+ time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000;
+
+ if (time.tv_nsec >= 1000000000)
+ {
+ time.tv_nsec -= 1000000000;
+ time.tv_sec++;
+ }
+
+ do
+ {
+ if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT)
+ {
+ pthread_mutex_unlock (&mutex);
+ return false;
+ }
+ }
+ while (! triggered);
+ }
+ }
+
+ if (! manualReset)
+ triggered = false;
+
+ pthread_mutex_unlock (&mutex);
+ return true;
+}
+
+void WaitableEvent::signal() const noexcept
+{
+ pthread_mutex_lock (&mutex);
+
+ if (! triggered)
+ {
+ triggered = true;
+ pthread_cond_broadcast (&condition);
+ }
+
+ pthread_mutex_unlock (&mutex);
+}
+
+void WaitableEvent::reset() const noexcept
+{
+ pthread_mutex_lock (&mutex);
+ triggered = false;
+ pthread_mutex_unlock (&mutex);
+}
+
+//==============================================================================
+void JUCE_CALLTYPE Thread::sleep (int millisecs)
+{
+ struct timespec time;
+ time.tv_sec = millisecs / 1000;
+ time.tv_nsec = (millisecs % 1000) * 1000000;
+ nanosleep (&time, nullptr);
+}
+
+void JUCE_CALLTYPE Process::terminate()
+{
+ #if JUCE_ANDROID
+ _exit (EXIT_FAILURE);
+ #else
+ std::_Exit (EXIT_FAILURE);
+ #endif
+}
+
+//==============================================================================
+const juce_wchar File::separator = '/';
+const String File::separatorString ("/");
+
+//==============================================================================
+File File::getCurrentWorkingDirectory()
+{
+ HeapBlock<char> heapBuffer;
+
+ char localBuffer [1024];
+ char* cwd = getcwd (localBuffer, sizeof (localBuffer) - 1);
+ size_t bufferSize = 4096;
+
+ while (cwd == nullptr && errno == ERANGE)
+ {
+ heapBuffer.malloc (bufferSize);
+ cwd = getcwd (heapBuffer, bufferSize - 1);
+ bufferSize += 1024;
+ }
+
+ return File (CharPointer_UTF8 (cwd));
+}
+
+bool File::setAsCurrentWorkingDirectory() const
+{
+ return chdir (getFullPathName().toUTF8()) == 0;
+}
+
+//==============================================================================
+// The unix siginterrupt function is deprecated - this does the same job.
+int juce_siginterrupt (int sig, int flag)
+{
+ struct ::sigaction act;
+ (void) ::sigaction (sig, nullptr, &act);
+
+ if (flag != 0)
+ act.sa_flags &= ~SA_RESTART;
+ else
+ act.sa_flags |= SA_RESTART;
+
+ return ::sigaction (sig, &act, nullptr);
+}
+
+//==============================================================================
+namespace
+{
+ #if JUCE_LINUX || (JUCE_IOS && ! __DARWIN_ONLY_64_BIT_INO_T) // (this iOS stuff is to avoid a simulator bug)
+ typedef struct stat64 juce_statStruct;
+ #define JUCE_STAT stat64
+ #else
+ typedef struct stat juce_statStruct;
+ #define JUCE_STAT stat
+ #endif
+
+ bool juce_stat (const String& fileName, juce_statStruct& info)
+ {
+ return fileName.isNotEmpty()
+ && JUCE_STAT (fileName.toUTF8(), &info) == 0;
+ }
+
+ // if this file doesn't exist, find a parent of it that does..
+ bool juce_doStatFS (File f, struct statfs& result)
+ {
+ for (int i = 5; --i >= 0;)
+ {
+ if (f.exists())
+ break;
+
+ f = f.getParentDirectory();
+ }
+
+ return statfs (f.getFullPathName().toUTF8(), &result) == 0;
+ }
+
+ void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ if (isDir != nullptr || fileSize != nullptr || modTime != nullptr || creationTime != nullptr)
+ {
+ juce_statStruct info;
+ const bool statOk = juce_stat (path, info);
+
+ if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
+ if (fileSize != nullptr) *fileSize = statOk ? info.st_size : 0;
+ if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0);
+ if (creationTime != nullptr) *creationTime = Time (statOk ? (int64) info.st_ctime * 1000 : 0);
+ }
+
+ if (isReadOnly != nullptr)
+ *isReadOnly = access (path.toUTF8(), W_OK) != 0;
+ }
+
+ Result getResultForErrno()
+ {
+ return Result::fail (String (strerror (errno)));
+ }
+
+ Result getResultForReturnValue (int value)
+ {
+ return value == -1 ? getResultForErrno() : Result::ok();
+ }
+
+ int getFD (void* handle) noexcept { return (int) (pointer_sized_int) handle; }
+ void* fdToVoidPointer (int fd) noexcept { return (void*) (pointer_sized_int) fd; }
+}
+
+bool File::isDirectory() const
+{
+ juce_statStruct info;
+
+ return fullPath.isEmpty()
+ || (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
+}
+
+bool File::exists() const
+{
+ return fullPath.isNotEmpty()
+ && access (fullPath.toUTF8(), F_OK) == 0;
+}
+
+bool File::existsAsFile() const
+{
+ return exists() && ! isDirectory();
+}
+
+int64 File::getSize() const
+{
+ juce_statStruct info;
+ return juce_stat (fullPath, info) ? info.st_size : 0;
+}
+
+uint64 File::getFileIdentifier() const
+{
+ juce_statStruct info;
+ return juce_stat (fullPath, info) ? (uint64) info.st_ino : 0;
+}
+
+//==============================================================================
+bool File::hasWriteAccess() const
+{
+ if (exists())
+ return access (fullPath.toUTF8(), W_OK) == 0;
+
+ if ((! isDirectory()) && fullPath.containsChar (separator))
+ return getParentDirectory().hasWriteAccess();
+
+ return false;
+}
+
+bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
+{
+ juce_statStruct info;
+ if (! juce_stat (fullPath, info))
+ return false;
+
+ info.st_mode &= 0777; // Just permissions
+
+ if (shouldBeReadOnly)
+ info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ else
+ // Give everybody write permission?
+ info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ return chmod (fullPath.toUTF8(), info.st_mode) == 0;
+}
+
+void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const
+{
+ modificationTime = 0;
+ accessTime = 0;
+ creationTime = 0;
+
+ juce_statStruct info;
+ if (juce_stat (fullPath, info))
+ {
+ modificationTime = (int64) info.st_mtime * 1000;
+ accessTime = (int64) info.st_atime * 1000;
+ creationTime = (int64) info.st_ctime * 1000;
+ }
+}
+
+bool File::setFileTimesInternal (int64 modificationTime, int64 accessTime, int64 /*creationTime*/) const
+{
+ juce_statStruct info;
+
+ if ((modificationTime != 0 || accessTime != 0) && juce_stat (fullPath, info))
+ {
+ struct utimbuf times;
+ times.actime = accessTime != 0 ? (time_t) (accessTime / 1000) : info.st_atime;
+ times.modtime = modificationTime != 0 ? (time_t) (modificationTime / 1000) : info.st_mtime;
+
+ return utime (fullPath.toUTF8(), ×) == 0;
+ }
+
+ return false;
+}
+
+bool File::deleteFile() const
+{
+ if (! exists())
+ return true;
+
+ if (isDirectory())
+ return rmdir (fullPath.toUTF8()) == 0;
+
+ return remove (fullPath.toUTF8()) == 0;
+}
+
+bool File::moveInternal (const File& dest) const
+{
+ if (rename (fullPath.toUTF8(), dest.getFullPathName().toUTF8()) == 0)
+ return true;
+
+ if (hasWriteAccess() && copyInternal (dest))
+ {
+ if (deleteFile())
+ return true;
+
+ dest.deleteFile();
+ }
+
+ return false;
+}
+
+Result File::createDirectoryInternal (const String& fileName) const
+{
+ return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777));
+}
+
+//=====================================================================
+int64 juce_fileSetPosition (void* handle, int64 pos)
+{
+ if (handle != 0 && lseek (getFD (handle), pos, SEEK_SET) == pos)
+ return pos;
+
+ return -1;
+}
+
+void FileInputStream::openHandle()
+{
+ const int f = open (file.getFullPathName().toUTF8(), O_RDONLY, 00644);
+
+ if (f != -1)
+ fileHandle = fdToVoidPointer (f);
+ else
+ status = getResultForErrno();
+}
+
+FileInputStream::~FileInputStream()
+{
+ if (fileHandle != 0)
+ close (getFD (fileHandle));
+}
+
+size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes)
+{
+ ssize_t result = 0;
+
+ if (fileHandle != 0)
+ {
+ result = ::read (getFD (fileHandle), buffer, numBytes);
+
+ if (result < 0)
+ {
+ status = getResultForErrno();
+ result = 0;
+ }
+ }
+
+ return (size_t) result;
+}
+
+//==============================================================================
+void FileOutputStream::openHandle()
+{
+ if (file.exists())
+ {
+ const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
+
+ if (f != -1)
+ {
+ currentPosition = lseek (f, 0, SEEK_END);
+
+ if (currentPosition >= 0)
+ {
+ fileHandle = fdToVoidPointer (f);
+ }
+ else
+ {
+ status = getResultForErrno();
+ close (f);
+ }
+ }
+ else
+ {
+ status = getResultForErrno();
+ }
+ }
+ else
+ {
+ const int f = open (file.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644);
+
+ if (f != -1)
+ fileHandle = fdToVoidPointer (f);
+ else
+ status = getResultForErrno();
+ }
+}
+
+void FileOutputStream::closeHandle()
+{
+ if (fileHandle != 0)
+ {
+ close (getFD (fileHandle));
+ fileHandle = 0;
+ }
+}
+
+ssize_t FileOutputStream::writeInternal (const void* const data, const size_t numBytes)
+{
+ ssize_t result = 0;
+
+ if (fileHandle != 0)
+ {
+ result = ::write (getFD (fileHandle), data, numBytes);
+
+ if (result == -1)
+ status = getResultForErrno();
+ }
+
+ return result;
+}
+
+void FileOutputStream::flushInternal()
+{
+ if (fileHandle != 0)
+ {
+ if (fsync (getFD (fileHandle)) == -1)
+ status = getResultForErrno();
+
+ #if JUCE_ANDROID
+ // This stuff tells the OS to asynchronously update the metadata
+ // that the OS has cached aboud the file - this metadata is used
+ // when the device is acting as a USB drive, and unless it's explicitly
+ // refreshed, it'll get out of step with the real file.
+ const LocalRef<jstring> t (javaString (file.getFullPathName()));
+ android.activity.callVoidMethod (JuceAppActivity.scanFile, t.get());
+ #endif
+ }
+}
+
+Result FileOutputStream::truncate()
+{
+ if (fileHandle == 0)
+ return status;
+
+ flush();
+ return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
+}
+
+//==============================================================================
+String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
+{
+ if (const char* s = ::getenv (name.toUTF8()))
+ return String::fromUTF8 (s);
+
+ return defaultValue;
+}
+
+//==============================================================================
+void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
+{
+ jassert (mode == readOnly || mode == readWrite);
+
+ if (range.getStart() > 0)
+ {
+ const long pageSize = sysconf (_SC_PAGE_SIZE);
+ range.setStart (range.getStart() - (range.getStart() % pageSize));
+ }
+
+ fileHandle = open (file.getFullPathName().toUTF8(),
+ mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
+
+ if (fileHandle != -1)
+ {
+ void* m = mmap (0, (size_t) range.getLength(),
+ mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
+ MAP_SHARED, fileHandle,
+ (off_t) range.getStart());
+
+ if (m != MAP_FAILED)
+ {
+ address = m;
+ madvise (m, (size_t) range.getLength(), MADV_SEQUENTIAL);
+ }
+ else
+ {
+ range = Range<int64>();
+ }
+ }
+}
+
+MemoryMappedFile::~MemoryMappedFile()
+{
+ if (address != nullptr)
+ munmap (address, (size_t) range.getLength());
+
+ if (fileHandle != 0)
+ close (fileHandle);
+}
+
+//==============================================================================
+#if JUCE_PROJUCER_LIVE_BUILD
+extern "C" const char* juce_getCurrentExecutablePath();
+#endif
+
+File juce_getExecutableFile();
+File juce_getExecutableFile()
+{
+ #if JUCE_PROJUCER_LIVE_BUILD
+ return File (juce_getCurrentExecutablePath());
+ #elif JUCE_ANDROID
+ return File (android.appFile);
+ #else
+ struct DLAddrReader
+ {
+ static String getFilename()
+ {
+ Dl_info exeInfo;
+ dladdr ((void*) juce_getExecutableFile, &exeInfo);
+ return CharPointer_UTF8 (exeInfo.dli_fname);
+ }
+ };
+
+ static String filename (DLAddrReader::getFilename());
+ return File::getCurrentWorkingDirectory().getChildFile (filename);
+ #endif
+}
+
+//==============================================================================
+int64 File::getBytesFreeOnVolume() const
+{
+ struct statfs buf;
+ if (juce_doStatFS (*this, buf))
+ return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user
+
+ return 0;
+}
+
+int64 File::getVolumeTotalSize() const
+{
+ struct statfs buf;
+ if (juce_doStatFS (*this, buf))
+ return (int64) buf.f_bsize * (int64) buf.f_blocks;
+
+ return 0;
+}
+
+String File::getVolumeLabel() const
+{
+ #if JUCE_MAC
+ struct VolAttrBuf
+ {
+ u_int32_t length;
+ attrreference_t mountPointRef;
+ char mountPointSpace [MAXPATHLEN];
+ } attrBuf;
+
+ struct attrlist attrList;
+ zerostruct (attrList); // (can't use "= { 0 }" on this object because it's typedef'ed as a C struct)
+ attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
+
+ File f (*this);
+
+ for (;;)
+ {
+ if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
+ return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
+ (int) attrBuf.mountPointRef.attr_length);
+
+ const File parent (f.getParentDirectory());
+
+ if (f == parent)
+ break;
+
+ f = parent;
+ }
+ #endif
+
+ return String();
+}
+
+int File::getVolumeSerialNumber() const
+{
+ int result = 0;
+/* int fd = open (getFullPathName().toUTF8(), O_RDONLY | O_NONBLOCK);
+
+ char info [512];
+
+ #ifndef HDIO_GET_IDENTITY
+ #define HDIO_GET_IDENTITY 0x030d
+ #endif
+
+ if (ioctl (fd, HDIO_GET_IDENTITY, info) == 0)
+ {
+ DBG (String (info + 20, 20));
+ result = String (info + 20, 20).trim().getIntValue();
+ }
+
+ close (fd);*/
+ return result;
+}
+
+//==============================================================================
+void juce_runSystemCommand (const String&);
+void juce_runSystemCommand (const String& command)
+{
+ int result = system (command.toUTF8());
+ (void) result;
+}
+
+String juce_getOutputFromCommand (const String&);
+String juce_getOutputFromCommand (const String& command)
+{
+ // slight bodge here, as we just pipe the output into a temp file and read it...
+ const File tempFile (File::getSpecialLocation (File::tempDirectory)
+ .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false));
+
+ juce_runSystemCommand (command + " > " + tempFile.getFullPathName());
+
+ String result (tempFile.loadFileAsString());
+ tempFile.deleteFile();
+ return result;
+}
+
+
+//==============================================================================
+#if JUCE_IOS
+class InterProcessLock::Pimpl
+{
+public:
+ Pimpl (const String&, int)
+ : handle (1), refCount (1) // On iOS just fake success..
+ {
+ }
+
+ int handle, refCount;
+};
+
+#else
+
+class InterProcessLock::Pimpl
+{
+public:
+ Pimpl (const String& lockName, const int timeOutMillisecs)
+ : handle (0), refCount (1)
+ {
+ #if JUCE_MAC
+ if (! createLockFile (File ("~/Library/Caches/com.juce.locks").getChildFile (lockName), timeOutMillisecs))
+ // Fallback if the user's home folder is on a network drive with no ability to lock..
+ createLockFile (File ("/tmp/com.juce.locks").getChildFile (lockName), timeOutMillisecs);
+
+ #else
+ File tempFolder ("/var/tmp");
+ if (! tempFolder.isDirectory())
+ tempFolder = "/tmp";
+
+ createLockFile (tempFolder.getChildFile (lockName), timeOutMillisecs);
+ #endif
+ }
+
+ ~Pimpl()
+ {
+ closeFile();
+ }
+
+ bool createLockFile (const File& file, const int timeOutMillisecs)
+ {
+ file.create();
+ handle = open (file.getFullPathName().toUTF8(), O_RDWR);
+
+ if (handle != 0)
+ {
+ struct flock fl;
+ zerostruct (fl);
+
+ fl.l_whence = SEEK_SET;
+ fl.l_type = F_WRLCK;
+
+ const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
+
+ for (;;)
+ {
+ const int result = fcntl (handle, F_SETLK, &fl);
+
+ if (result >= 0)
+ return true;
+
+ const int error = errno;
+
+ if (error != EINTR)
+ {
+ if (error == EBADF || error == ENOTSUP)
+ return false;
+
+ if (timeOutMillisecs == 0
+ || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
+ break;
+
+ Thread::sleep (10);
+ }
+ }
+ }
+
+ closeFile();
+ return true; // only false if there's a file system error. Failure to lock still returns true.
+ }
+
+ void closeFile()
+ {
+ if (handle != 0)
+ {
+ struct flock fl;
+ zerostruct (fl);
+
+ fl.l_whence = SEEK_SET;
+ fl.l_type = F_UNLCK;
+
+ while (! (fcntl (handle, F_SETLKW, &fl) >= 0 || errno != EINTR))
+ {}
+
+ close (handle);
+ handle = 0;
+ }
+ }
+
+ int handle, refCount;
+};
+#endif
+
+InterProcessLock::InterProcessLock (const String& nm) : name (nm)
+{
+}
+
+InterProcessLock::~InterProcessLock()
+{
+}
+
+bool InterProcessLock::enter (const int timeOutMillisecs)
+{
+ const ScopedLock sl (lock);
+
+ if (pimpl == nullptr)
+ {
+ pimpl = new Pimpl (name, timeOutMillisecs);
+
+ if (pimpl->handle == 0)
+ pimpl = nullptr;
+ }
+ else
+ {
+ pimpl->refCount++;
+ }
+
+ return pimpl != nullptr;
+}
+
+void InterProcessLock::exit()
+{
+ const ScopedLock sl (lock);
+
+ // Trying to release the lock too many times!
+ jassert (pimpl != nullptr);
+
+ if (pimpl != nullptr && --(pimpl->refCount) == 0)
+ pimpl = nullptr;
+}
+
+//==============================================================================
+void JUCE_API juce_threadEntryPoint (void*);
+
+extern "C" void* threadEntryProc (void*);
+extern "C" void* threadEntryProc (void* userData)
+{
+ JUCE_AUTORELEASEPOOL
+ {
+ #if JUCE_ANDROID
+ const AndroidThreadScope androidEnv;
+ #endif
+
+ juce_threadEntryPoint (userData);
+ }
+
+ return nullptr;
+}
+
+void Thread::launchThread()
+{
+ threadHandle = 0;
+ pthread_t handle = 0;
+
+ if (pthread_create (&handle, 0, threadEntryProc, this) == 0)
+ {
+ pthread_detach (handle);
+ threadHandle = (void*) handle;
+ threadId = (ThreadID) threadHandle;
+ }
+}
+
+void Thread::closeThreadHandle()
+{
+ threadId = 0;
+ threadHandle = 0;
+}
+
+void Thread::killThread()
+{
+ if (threadHandle != 0)
+ {
+ #if JUCE_ANDROID
+ jassertfalse; // pthread_cancel not available!
+ #else
+ pthread_cancel ((pthread_t) threadHandle);
+ #endif
+ }
+}
+
+void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)
+{
+ #if JUCE_IOS || (JUCE_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+ JUCE_AUTORELEASEPOOL
+ {
+ [[NSThread currentThread] setName: juceStringToNS (name)];
+ }
+ #elif JUCE_LINUX
+ #if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
+ pthread_setname_np (pthread_self(), name.toRawUTF8());
+ #else
+ prctl (PR_SET_NAME, name.toRawUTF8(), 0, 0, 0);
+ #endif
+ #endif
+}
+
+bool Thread::setThreadPriority (void* handle, int priority)
+{
+ struct sched_param param;
+ int policy;
+ priority = jlimit (0, 10, priority);
+
+ if (handle == nullptr)
+ handle = (void*) pthread_self();
+
+ if (pthread_getschedparam ((pthread_t) handle, &policy, ¶m) != 0)
+ return false;
+
+ policy = priority == 0 ? SCHED_OTHER : SCHED_RR;
+
+ const int minPriority = sched_get_priority_min (policy);
+ const int maxPriority = sched_get_priority_max (policy);
+
+ param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority;
+ return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0;
+}
+
+Thread::ThreadID JUCE_CALLTYPE Thread::getCurrentThreadId()
+{
+ return (ThreadID) pthread_self();
+}
+
+void JUCE_CALLTYPE Thread::yield()
+{
+ sched_yield();
+}
+
+//==============================================================================
+/* Remove this macro if you're having problems compiling the cpu affinity
+ calls (the API for these has changed about quite a bit in various Linux
+ versions, and a lot of distros seem to ship with obsolete versions)
+*/
+#if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES)
+ #define SUPPORT_AFFINITIES 1
+#endif
+
+void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
+{
+ #if SUPPORT_AFFINITIES
+ cpu_set_t affinity;
+ CPU_ZERO (&affinity);
+
+ for (int i = 0; i < 32; ++i)
+ if ((affinityMask & (1 << i)) != 0)
+ CPU_SET (i, &affinity);
+
+ /*
+ N.B. If this line causes a compile error, then you've probably not got the latest
+ version of glibc installed.
+
+ If you don't want to update your copy of glibc and don't care about cpu affinities,
+ then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0.
+ */
+ sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity);
+ sched_yield();
+
+ #else
+ /* affinities aren't supported because either the appropriate header files weren't found,
+ or the SUPPORT_AFFINITIES macro was turned off
+ */
+ jassertfalse;
+ (void) affinityMask;
+ #endif
+}
+
+//==============================================================================
+bool DynamicLibrary::open (const String& name)
+{
+ close();
+ handle = dlopen (name.isEmpty() ? nullptr : name.toUTF8().getAddress(), RTLD_LOCAL | RTLD_NOW);
+ return handle != nullptr;
+}
+
+void DynamicLibrary::close()
+{
+ if (handle != nullptr)
+ {
+ dlclose (handle);
+ handle = nullptr;
+ }
+}
+
+void* DynamicLibrary::getFunction (const String& functionName) noexcept
+{
+ return handle != nullptr ? dlsym (handle, functionName.toUTF8()) : nullptr;
+}
+
+
+
+//==============================================================================
+class ChildProcess::ActiveProcess
+{
+public:
+ ActiveProcess (const StringArray& arguments, int streamFlags)
+ : childPID (0), pipeHandle (0), readHandle (0)
+ {
+ // Looks like you're trying to launch a non-existent exe or a folder (perhaps on OSX
+ // you're trying to launch the .app folder rather than the actual binary inside it?)
+ jassert ((! arguments[0].containsChar ('/'))
+ || File::getCurrentWorkingDirectory().getChildFile (arguments[0]).existsAsFile());
+
+ int pipeHandles[2] = { 0 };
+
+ if (pipe (pipeHandles) == 0)
+ {
+ const pid_t result = fork();
+
+ if (result < 0)
+ {
+ close (pipeHandles[0]);
+ close (pipeHandles[1]);
+ }
+ else if (result == 0)
+ {
+ // we're the child process..
+ close (pipeHandles[0]); // close the read handle
+
+ if ((streamFlags & wantStdOut) != 0)
+ dup2 (pipeHandles[1], 1); // turns the pipe into stdout
+ else
+ close (STDOUT_FILENO);
+
+ if ((streamFlags & wantStdErr) != 0)
+ dup2 (pipeHandles[1], 2);
+ else
+ close (STDERR_FILENO);
+
+ close (pipeHandles[1]);
+
+ Array<char*> argv;
+ for (int i = 0; i < arguments.size(); ++i)
+ if (arguments[i].isNotEmpty())
+ argv.add (const_cast<char*> (arguments[i].toUTF8().getAddress()));
+
+ argv.add (nullptr);
+
+ execvp (argv[0], argv.getRawDataPointer());
+ exit (-1);
+ }
+ else
+ {
+ // we're the parent process..
+ childPID = result;
+ pipeHandle = pipeHandles[0];
+ close (pipeHandles[1]); // close the write handle
+ }
+ }
+ }
+
+ ~ActiveProcess()
+ {
+ if (readHandle != 0)
+ fclose (readHandle);
+
+ if (pipeHandle != 0)
+ close (pipeHandle);
+ }
+
+ bool isRunning() const noexcept
+ {
+ if (childPID != 0)
+ {
+ int childState;
+ const int pid = waitpid (childPID, &childState, WNOHANG);
+ return pid == 0 || ! (WIFEXITED (childState) || WIFSIGNALED (childState));
+ }
+
+ return false;
+ }
+
+ int read (void* const dest, const int numBytes) noexcept
+ {
+ jassert (dest != nullptr);
+
+ #ifdef fdopen
+ #error // the zlib headers define this function as NULL!
+ #endif
+
+ if (readHandle == 0 && childPID != 0)
+ readHandle = fdopen (pipeHandle, "r");
+
+ if (readHandle != 0)
+ return (int) fread (dest, 1, (size_t) numBytes, readHandle);
+
+ return 0;
+ }
+
+ bool killProcess() const noexcept
+ {
+ return ::kill (childPID, SIGKILL) == 0;
+ }
+
+ uint32 getExitCode() const noexcept
+ {
+ if (childPID != 0)
+ {
+ int childState = 0;
+ const int pid = waitpid (childPID, &childState, WNOHANG);
+
+ if (pid >= 0 && WIFEXITED (childState))
+ return WEXITSTATUS (childState);
+ }
+
+ return 0;
+ }
+
+ int childPID;
+
+private:
+ int pipeHandle;
+ FILE* readHandle;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess)
+};
+
+bool ChildProcess::start (const String& command, int streamFlags)
+{
+ return start (StringArray::fromTokens (command, true), streamFlags);
+}
+
+bool ChildProcess::start (const StringArray& args, int streamFlags)
+{
+ if (args.size() == 0)
+ return false;
+
+ activeProcess = new ActiveProcess (args, streamFlags);
+
+ if (activeProcess->childPID == 0)
+ activeProcess = nullptr;
+
+ return activeProcess != nullptr;
+}
+
+//==============================================================================
+struct HighResolutionTimer::Pimpl
+{
+ Pimpl (HighResolutionTimer& t) : owner (t), thread (0), shouldStop (false)
+ {
+ }
+
+ ~Pimpl()
+ {
+ jassert (thread == 0);
+ }
+
+ void start (int newPeriod)
+ {
+ if (periodMs != newPeriod)
+ {
+ if (thread != pthread_self())
+ {
+ stop();
+
+ periodMs = newPeriod;
+ shouldStop = false;
+
+ if (pthread_create (&thread, nullptr, timerThread, this) == 0)
+ setThreadToRealtime (thread, (uint64) newPeriod);
+ else
+ jassertfalse;
+ }
+ else
+ {
+ periodMs = newPeriod;
+ shouldStop = false;
+ }
+ }
+ }
+
+ void stop()
+ {
+ if (thread != 0)
+ {
+ shouldStop = true;
+
+ while (thread != 0 && thread != pthread_self())
+ Thread::yield();
+ }
+ }
+
+ HighResolutionTimer& owner;
+ int volatile periodMs;
+
+private:
+ pthread_t thread;
+ bool volatile shouldStop;
+
+ static void* timerThread (void* param)
+ {
+ #if JUCE_ANDROID
+ const AndroidThreadScope androidEnv;
+ #else
+ int dummy;
+ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &dummy);
+ #endif
+
+ reinterpret_cast<Pimpl*> (param)->timerThread();
+ return nullptr;
+ }
+
+ void timerThread()
+ {
+ int lastPeriod = periodMs;
+ Clock clock (lastPeriod);
+
+ while (! shouldStop)
+ {
+ clock.wait();
+ owner.hiResTimerCallback();
+
+ if (lastPeriod != periodMs)
+ {
+ lastPeriod = periodMs;
+ clock = Clock (lastPeriod);
+ }
+ }
+
+ periodMs = 0;
+ thread = 0;
+ }
+
+ struct Clock
+ {
+ #if JUCE_MAC || JUCE_IOS
+ Clock (double millis) noexcept
+ {
+ mach_timebase_info_data_t timebase;
+ (void) mach_timebase_info (&timebase);
+ delta = (((uint64_t) (millis * 1000000.0)) * timebase.denom) / timebase.numer;
+ time = mach_absolute_time();
+ }
+
+ void wait() noexcept
+ {
+ time += delta;
+ mach_wait_until (time);
+ }
+
+ uint64_t time, delta;
+
+ #elif JUCE_ANDROID
+ Clock (double millis) noexcept : delta ((uint64) (millis * 1000000))
+ {
+ }
+
+ void wait() noexcept
+ {
+ struct timespec t;
+ t.tv_sec = (time_t) (delta / 1000000000);
+ t.tv_nsec = (long) (delta % 1000000000);
+ nanosleep (&t, nullptr);
+ }
+
+ uint64 delta;
+ #else
+ Clock (double millis) noexcept : delta ((uint64) (millis * 1000000))
+ {
+ struct timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+ time = 1000000000 * (int64) t.tv_sec + t.tv_nsec;
+ }
+
+ void wait() noexcept
+ {
+ time += delta;
+
+ struct timespec t;
+ t.tv_sec = (time_t) (time / 1000000000);
+ t.tv_nsec = (long) (time % 1000000000);
+
+ clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &t, nullptr);
+ }
+
+ uint64 time, delta;
+ #endif
+ };
+
+ static bool setThreadToRealtime (pthread_t thread, uint64 periodMs)
+ {
+ #if JUCE_MAC || JUCE_IOS
+ thread_time_constraint_policy_data_t policy;
+ policy.period = (uint32_t) (periodMs * 1000000);
+ policy.computation = 50000;
+ policy.constraint = policy.period;
+ policy.preemptible = true;
+
+ return thread_policy_set (pthread_mach_thread_np (thread),
+ THREAD_TIME_CONSTRAINT_POLICY,
+ (thread_policy_t) &policy,
+ THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;
+
+ #else
+ (void) periodMs;
+ struct sched_param param;
+ param.sched_priority = sched_get_priority_max (SCHED_RR);
+ return pthread_setschedparam (thread, SCHED_RR, ¶m) == 0;
+
+ #endif
+ }
+
+ JUCE_DECLARE_NON_COPYABLE (Pimpl)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_ComSmartPtr.h b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_ComSmartPtr.h
new file mode 100644
index 0000000..0dc0efc
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_ComSmartPtr.h
@@ -0,0 +1,170 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_WIN32_COMSMARTPTR_H_INCLUDED
+#define JUCE_WIN32_COMSMARTPTR_H_INCLUDED
+
+#if ! (defined (_MSC_VER) || defined (__uuidof))
+template<typename Type> struct UUIDGetter { static CLSID get() { jassertfalse; return CLSID(); } };
+#define __uuidof(x) UUIDGetter<x>::get()
+#endif
+
+inline GUID uuidFromString (const char* const s) noexcept
+{
+ unsigned long p0;
+ unsigned int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
+
+ #ifndef _MSC_VER
+ sscanf
+ #else
+ sscanf_s
+ #endif
+ (s, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ &p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10);
+
+ GUID g = { p0, (uint16) p1, (uint16) p2, { (uint8) p3, (uint8) p4, (uint8) p5, (uint8) p6,
+ (uint8) p7, (uint8) p8, (uint8) p9, (uint8) p10 }};
+ return g;
+}
+
+//==============================================================================
+/** A simple COM smart pointer.
+*/
+template <class ComClass>
+class ComSmartPtr
+{
+public:
+ ComSmartPtr() throw() : p (0) {}
+ ComSmartPtr (ComClass* const obj) : p (obj) { if (p) p->AddRef(); }
+ ComSmartPtr (const ComSmartPtr<ComClass>& other) : p (other.p) { if (p) p->AddRef(); }
+ ~ComSmartPtr() { release(); }
+
+ operator ComClass*() const throw() { return p; }
+ ComClass& operator*() const throw() { return *p; }
+ ComClass* operator->() const throw() { return p; }
+
+ ComSmartPtr& operator= (ComClass* const newP)
+ {
+ if (newP != 0) newP->AddRef();
+ release();
+ p = newP;
+ return *this;
+ }
+
+ ComSmartPtr& operator= (const ComSmartPtr<ComClass>& newP) { return operator= (newP.p); }
+
+ // Releases and nullifies this pointer and returns its address
+ ComClass** resetAndGetPointerAddress()
+ {
+ release();
+ p = 0;
+ return &p;
+ }
+
+ HRESULT CoCreateInstance (REFCLSID classUUID, DWORD dwClsContext = CLSCTX_INPROC_SERVER)
+ {
+ HRESULT hr = ::CoCreateInstance (classUUID, 0, dwClsContext, __uuidof (ComClass), (void**) resetAndGetPointerAddress());
+ jassert (hr != CO_E_NOTINITIALIZED); // You haven't called CoInitialize for the current thread!
+ return hr;
+ }
+
+ template <class OtherComClass>
+ HRESULT QueryInterface (REFCLSID classUUID, ComSmartPtr<OtherComClass>& destObject) const
+ {
+ if (p == 0)
+ return E_POINTER;
+
+ return p->QueryInterface (classUUID, (void**) destObject.resetAndGetPointerAddress());
+ }
+
+ template <class OtherComClass>
+ HRESULT QueryInterface (ComSmartPtr<OtherComClass>& destObject) const
+ {
+ return this->QueryInterface (__uuidof (OtherComClass), destObject);
+ }
+
+private:
+ ComClass* p;
+
+ void release() { if (p != 0) p->Release(); }
+
+ ComClass** operator&() throw(); // private to avoid it being used accidentally
+};
+
+//==============================================================================
+#define JUCE_COMRESULT HRESULT __stdcall
+
+//==============================================================================
+template <class ComClass>
+class ComBaseClassHelperBase : public ComClass
+{
+public:
+ ComBaseClassHelperBase (unsigned int initialRefCount) : refCount (initialRefCount) {}
+ virtual ~ComBaseClassHelperBase() {}
+
+ ULONG __stdcall AddRef() { return ++refCount; }
+ ULONG __stdcall Release() { const ULONG r = --refCount; if (r == 0) delete this; return r; }
+
+protected:
+ ULONG refCount;
+
+ JUCE_COMRESULT QueryInterface (REFIID refId, void** result)
+ {
+ if (refId == IID_IUnknown)
+ return castToType <IUnknown> (result);
+
+ *result = 0;
+ return E_NOINTERFACE;
+ }
+
+ template <class Type>
+ JUCE_COMRESULT castToType (void** result)
+ {
+ this->AddRef(); *result = dynamic_cast <Type*> (this); return S_OK;
+ }
+};
+
+/** Handy base class for writing COM objects, providing ref-counting and a basic QueryInterface method.
+*/
+template <class ComClass>
+class ComBaseClassHelper : public ComBaseClassHelperBase <ComClass>
+{
+public:
+ ComBaseClassHelper (unsigned int initialRefCount = 1) : ComBaseClassHelperBase <ComClass> (initialRefCount) {}
+ ~ComBaseClassHelper() {}
+
+ JUCE_COMRESULT QueryInterface (REFIID refId, void** result)
+ {
+ if (refId == __uuidof (ComClass))
+ return this->template castToType <ComClass> (result);
+
+ return ComBaseClassHelperBase <ComClass>::QueryInterface (refId, result);
+ }
+};
+
+#endif // JUCE_WIN32_COMSMARTPTR_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Files.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Files.cpp
new file mode 100644
index 0000000..a77aa5a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Files.cpp
@@ -0,0 +1,999 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef INVALID_FILE_ATTRIBUTES
+ #define INVALID_FILE_ATTRIBUTES ((DWORD) -1)
+#endif
+
+//==============================================================================
+namespace WindowsFileHelpers
+{
+ DWORD getAtts (const String& path)
+ {
+ return GetFileAttributes (path.toWideCharPointer());
+ }
+
+ int64 fileTimeToTime (const FILETIME* const ft)
+ {
+ static_jassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME)); // tell me if this fails!
+
+ return (int64) ((reinterpret_cast<const ULARGE_INTEGER*> (ft)->QuadPart - 116444736000000000LL) / 10000);
+ }
+
+ FILETIME* timeToFileTime (const int64 time, FILETIME* const ft) noexcept
+ {
+ if (time <= 0)
+ return nullptr;
+
+ reinterpret_cast<ULARGE_INTEGER*> (ft)->QuadPart = (ULONGLONG) (time * 10000 + 116444736000000000LL);
+ return ft;
+ }
+
+ String getDriveFromPath (String path)
+ {
+ if (path.isNotEmpty() && path[1] == ':' && path[2] == 0)
+ path << '\\';
+
+ const size_t numBytes = CharPointer_UTF16::getBytesRequiredFor (path.getCharPointer()) + 4;
+ HeapBlock<WCHAR> pathCopy;
+ pathCopy.calloc (numBytes, 1);
+ path.copyToUTF16 (pathCopy, numBytes);
+
+ if (PathStripToRoot (pathCopy))
+ path = static_cast <const WCHAR*> (pathCopy);
+
+ return path;
+ }
+
+ int64 getDiskSpaceInfo (const String& path, const bool total)
+ {
+ ULARGE_INTEGER spc, tot, totFree;
+
+ if (GetDiskFreeSpaceEx (getDriveFromPath (path).toWideCharPointer(), &spc, &tot, &totFree))
+ return total ? (int64) tot.QuadPart
+ : (int64) spc.QuadPart;
+
+ return 0;
+ }
+
+ unsigned int getWindowsDriveType (const String& path)
+ {
+ return GetDriveType (getDriveFromPath (path).toWideCharPointer());
+ }
+
+ File getSpecialFolderPath (int type)
+ {
+ WCHAR path [MAX_PATH + 256];
+
+ if (SHGetSpecialFolderPath (0, path, type, FALSE))
+ return File (String (path));
+
+ return File();
+ }
+
+ File getModuleFileName (HINSTANCE moduleHandle)
+ {
+ WCHAR dest [MAX_PATH + 256];
+ dest[0] = 0;
+ GetModuleFileName (moduleHandle, dest, (DWORD) numElementsInArray (dest));
+ return File (String (dest));
+ }
+
+ Result getResultForLastError()
+ {
+ TCHAR messageBuffer [256] = { 0 };
+
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, GetLastError(), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ messageBuffer, (DWORD) numElementsInArray (messageBuffer) - 1, nullptr);
+
+ return Result::fail (String (messageBuffer));
+ }
+}
+
+//==============================================================================
+const juce_wchar File::separator = '\\';
+const String File::separatorString ("\\");
+
+
+//==============================================================================
+bool File::exists() const
+{
+ return fullPath.isNotEmpty()
+ && WindowsFileHelpers::getAtts (fullPath) != INVALID_FILE_ATTRIBUTES;
+}
+
+bool File::existsAsFile() const
+{
+ return fullPath.isNotEmpty()
+ && (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+bool File::isDirectory() const
+{
+ const DWORD attr = WindowsFileHelpers::getAtts (fullPath);
+ return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) && (attr != INVALID_FILE_ATTRIBUTES);
+}
+
+bool File::hasWriteAccess() const
+{
+ if (exists())
+ return (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_READONLY) == 0;
+
+ // on windows, it seems that even read-only directories can still be written into,
+ // so checking the parent directory's permissions would return the wrong result..
+ return true;
+}
+
+bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
+{
+ const DWORD oldAtts = WindowsFileHelpers::getAtts (fullPath);
+
+ if (oldAtts == INVALID_FILE_ATTRIBUTES)
+ return false;
+
+ const DWORD newAtts = shouldBeReadOnly ? (oldAtts | FILE_ATTRIBUTE_READONLY)
+ : (oldAtts & ~FILE_ATTRIBUTE_READONLY);
+ return newAtts == oldAtts
+ || SetFileAttributes (fullPath.toWideCharPointer(), newAtts) != FALSE;
+}
+
+bool File::isHidden() const
+{
+ return (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_HIDDEN) != 0;
+}
+
+//==============================================================================
+bool File::deleteFile() const
+{
+ if (! exists())
+ return true;
+
+ return isDirectory() ? RemoveDirectory (fullPath.toWideCharPointer()) != 0
+ : DeleteFile (fullPath.toWideCharPointer()) != 0;
+}
+
+bool File::moveToTrash() const
+{
+ if (! exists())
+ return true;
+
+ // The string we pass in must be double null terminated..
+ const size_t numBytes = CharPointer_UTF16::getBytesRequiredFor (fullPath.getCharPointer()) + 8;
+ HeapBlock<WCHAR> doubleNullTermPath;
+ doubleNullTermPath.calloc (numBytes, 1);
+ fullPath.copyToUTF16 (doubleNullTermPath, numBytes);
+
+ SHFILEOPSTRUCT fos = { 0 };
+ fos.wFunc = FO_DELETE;
+ fos.pFrom = doubleNullTermPath;
+ fos.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION
+ | FOF_NOCONFIRMMKDIR | FOF_RENAMEONCOLLISION;
+
+ return SHFileOperation (&fos) == 0;
+}
+
+bool File::copyInternal (const File& dest) const
+{
+ return CopyFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer(), false) != 0;
+}
+
+bool File::moveInternal (const File& dest) const
+{
+ return MoveFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer()) != 0;
+}
+
+Result File::createDirectoryInternal (const String& fileName) const
+{
+ return CreateDirectory (fileName.toWideCharPointer(), 0) ? Result::ok()
+ : WindowsFileHelpers::getResultForLastError();
+}
+
+//==============================================================================
+int64 juce_fileSetPosition (void* handle, int64 pos)
+{
+ LARGE_INTEGER li;
+ li.QuadPart = pos;
+ li.LowPart = SetFilePointer ((HANDLE) handle, (LONG) li.LowPart, &li.HighPart, FILE_BEGIN); // (returns -1 if it fails)
+ return li.QuadPart;
+}
+
+void FileInputStream::openHandle()
+{
+ HANDLE h = CreateFile (file.getFullPathName().toWideCharPointer(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
+
+ if (h != INVALID_HANDLE_VALUE)
+ fileHandle = (void*) h;
+ else
+ status = WindowsFileHelpers::getResultForLastError();
+}
+
+FileInputStream::~FileInputStream()
+{
+ CloseHandle ((HANDLE) fileHandle);
+}
+
+size_t FileInputStream::readInternal (void* buffer, size_t numBytes)
+{
+ if (fileHandle != 0)
+ {
+ DWORD actualNum = 0;
+ if (! ReadFile ((HANDLE) fileHandle, buffer, (DWORD) numBytes, &actualNum, 0))
+ status = WindowsFileHelpers::getResultForLastError();
+
+ return (size_t) actualNum;
+ }
+
+ return 0;
+}
+
+//==============================================================================
+void FileOutputStream::openHandle()
+{
+ HANDLE h = CreateFile (file.getFullPathName().toWideCharPointer(), GENERIC_WRITE, FILE_SHARE_READ, 0,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ LARGE_INTEGER li;
+ li.QuadPart = 0;
+ li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_END);
+
+ if (li.LowPart != INVALID_SET_FILE_POINTER)
+ {
+ fileHandle = (void*) h;
+ currentPosition = li.QuadPart;
+ return;
+ }
+ }
+
+ status = WindowsFileHelpers::getResultForLastError();
+}
+
+void FileOutputStream::closeHandle()
+{
+ CloseHandle ((HANDLE) fileHandle);
+}
+
+ssize_t FileOutputStream::writeInternal (const void* buffer, size_t numBytes)
+{
+ if (fileHandle != nullptr)
+ {
+ DWORD actualNum = 0;
+ if (! WriteFile ((HANDLE) fileHandle, buffer, (DWORD) numBytes, &actualNum, 0))
+ status = WindowsFileHelpers::getResultForLastError();
+
+ return (ssize_t) actualNum;
+ }
+
+ return 0;
+}
+
+void FileOutputStream::flushInternal()
+{
+ if (fileHandle != nullptr)
+ if (! FlushFileBuffers ((HANDLE) fileHandle))
+ status = WindowsFileHelpers::getResultForLastError();
+}
+
+Result FileOutputStream::truncate()
+{
+ if (fileHandle == nullptr)
+ return status;
+
+ flush();
+ return SetEndOfFile ((HANDLE) fileHandle) ? Result::ok()
+ : WindowsFileHelpers::getResultForLastError();
+}
+
+//==============================================================================
+void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
+{
+ jassert (mode == readOnly || mode == readWrite);
+
+ if (range.getStart() > 0)
+ {
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo (&systemInfo);
+
+ range.setStart (range.getStart() - (range.getStart() % systemInfo.dwAllocationGranularity));
+ }
+
+ DWORD accessMode = GENERIC_READ, createType = OPEN_EXISTING;
+ DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
+
+ if (mode == readWrite)
+ {
+ accessMode = GENERIC_READ | GENERIC_WRITE;
+ createType = OPEN_ALWAYS;
+ protect = PAGE_READWRITE;
+ access = FILE_MAP_ALL_ACCESS;
+ }
+
+ HANDLE h = CreateFile (file.getFullPathName().toWideCharPointer(), accessMode, FILE_SHARE_READ, 0,
+ createType, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ fileHandle = (void*) h;
+
+ HANDLE mappingHandle = CreateFileMapping (h, 0, protect, (DWORD) (range.getEnd() >> 32), (DWORD) range.getEnd(), 0);
+
+ if (mappingHandle != 0)
+ {
+ address = MapViewOfFile (mappingHandle, access, (DWORD) (range.getStart() >> 32),
+ (DWORD) range.getStart(), (SIZE_T) range.getLength());
+
+ if (address == nullptr)
+ range = Range<int64>();
+
+ CloseHandle (mappingHandle);
+ }
+ }
+}
+
+MemoryMappedFile::~MemoryMappedFile()
+{
+ if (address != nullptr)
+ UnmapViewOfFile (address);
+
+ if (fileHandle != nullptr)
+ CloseHandle ((HANDLE) fileHandle);
+}
+
+//==============================================================================
+int64 File::getSize() const
+{
+ WIN32_FILE_ATTRIBUTE_DATA attributes;
+
+ if (GetFileAttributesEx (fullPath.toWideCharPointer(), GetFileExInfoStandard, &attributes))
+ return (((int64) attributes.nFileSizeHigh) << 32) | attributes.nFileSizeLow;
+
+ return 0;
+}
+
+void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const
+{
+ using namespace WindowsFileHelpers;
+ WIN32_FILE_ATTRIBUTE_DATA attributes;
+
+ if (GetFileAttributesEx (fullPath.toWideCharPointer(), GetFileExInfoStandard, &attributes))
+ {
+ modificationTime = fileTimeToTime (&attributes.ftLastWriteTime);
+ creationTime = fileTimeToTime (&attributes.ftCreationTime);
+ accessTime = fileTimeToTime (&attributes.ftLastAccessTime);
+ }
+ else
+ {
+ creationTime = accessTime = modificationTime = 0;
+ }
+}
+
+bool File::setFileTimesInternal (int64 modificationTime, int64 accessTime, int64 creationTime) const
+{
+ using namespace WindowsFileHelpers;
+
+ bool ok = false;
+ HANDLE h = CreateFile (fullPath.toWideCharPointer(), GENERIC_WRITE, FILE_SHARE_READ, 0,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ FILETIME m, a, c;
+
+ ok = SetFileTime (h,
+ timeToFileTime (creationTime, &c),
+ timeToFileTime (accessTime, &a),
+ timeToFileTime (modificationTime, &m)) != 0;
+
+ CloseHandle (h);
+ }
+
+ return ok;
+}
+
+//==============================================================================
+void File::findFileSystemRoots (Array<File>& destArray)
+{
+ TCHAR buffer [2048] = { 0 };
+ GetLogicalDriveStrings (2048, buffer);
+
+ const TCHAR* n = buffer;
+ StringArray roots;
+
+ while (*n != 0)
+ {
+ roots.add (String (n));
+
+ while (*n++ != 0)
+ {}
+ }
+
+ roots.sort (true);
+
+ for (int i = 0; i < roots.size(); ++i)
+ destArray.add (roots [i]);
+}
+
+//==============================================================================
+String File::getVolumeLabel() const
+{
+ TCHAR dest[64];
+ if (! GetVolumeInformation (WindowsFileHelpers::getDriveFromPath (getFullPathName()).toWideCharPointer(), dest,
+ (DWORD) numElementsInArray (dest), 0, 0, 0, 0, 0))
+ dest[0] = 0;
+
+ return dest;
+}
+
+int File::getVolumeSerialNumber() const
+{
+ TCHAR dest[64];
+ DWORD serialNum;
+
+ if (! GetVolumeInformation (WindowsFileHelpers::getDriveFromPath (getFullPathName()).toWideCharPointer(), dest,
+ (DWORD) numElementsInArray (dest), &serialNum, 0, 0, 0, 0))
+ return 0;
+
+ return (int) serialNum;
+}
+
+int64 File::getBytesFreeOnVolume() const
+{
+ return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), false);
+}
+
+int64 File::getVolumeTotalSize() const
+{
+ return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), true);
+}
+
+uint64 File::getFileIdentifier() const
+{
+ uint64 result = 0;
+
+ HANDLE h = CreateFile (getFullPathName().toWideCharPointer(),
+ GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ BY_HANDLE_FILE_INFORMATION info;
+ zerostruct (info);
+
+ if (GetFileInformationByHandle (h, &info))
+ result = (((uint64) info.nFileIndexHigh) << 32) | info.nFileIndexLow;
+
+ CloseHandle (h);
+ }
+
+ return result;
+}
+
+//==============================================================================
+bool File::isOnCDRomDrive() const
+{
+ return WindowsFileHelpers::getWindowsDriveType (getFullPathName()) == DRIVE_CDROM;
+}
+
+bool File::isOnHardDisk() const
+{
+ if (fullPath.isEmpty())
+ return false;
+
+ const unsigned int n = WindowsFileHelpers::getWindowsDriveType (getFullPathName());
+
+ if (fullPath.toLowerCase()[0] <= 'b' && fullPath[1] == ':')
+ return n != DRIVE_REMOVABLE;
+
+ return n != DRIVE_CDROM && n != DRIVE_REMOTE;
+}
+
+bool File::isOnRemovableDrive() const
+{
+ if (fullPath.isEmpty())
+ return false;
+
+ const unsigned int n = WindowsFileHelpers::getWindowsDriveType (getFullPathName());
+
+ return n == DRIVE_CDROM
+ || n == DRIVE_REMOTE
+ || n == DRIVE_REMOVABLE
+ || n == DRIVE_RAMDISK;
+}
+
+//==============================================================================
+File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type)
+{
+ int csidlType = 0;
+
+ switch (type)
+ {
+ case userHomeDirectory: csidlType = CSIDL_PROFILE; break;
+ case userDocumentsDirectory: csidlType = CSIDL_PERSONAL; break;
+ case userDesktopDirectory: csidlType = CSIDL_DESKTOP; break;
+ case userApplicationDataDirectory: csidlType = CSIDL_APPDATA; break;
+ case commonApplicationDataDirectory: csidlType = CSIDL_COMMON_APPDATA; break;
+ case commonDocumentsDirectory: csidlType = CSIDL_COMMON_DOCUMENTS; break;
+ case globalApplicationsDirectory: csidlType = CSIDL_PROGRAM_FILES; break;
+ case userMusicDirectory: csidlType = 0x0d; /*CSIDL_MYMUSIC*/ break;
+ case userMoviesDirectory: csidlType = 0x0e; /*CSIDL_MYVIDEO*/ break;
+ case userPicturesDirectory: csidlType = 0x27; /*CSIDL_MYPICTURES*/ break;
+
+ case tempDirectory:
+ {
+ WCHAR dest [2048];
+ dest[0] = 0;
+ GetTempPath ((DWORD) numElementsInArray (dest), dest);
+ return File (String (dest));
+ }
+
+ case windowsSystemDirectory:
+ {
+ WCHAR dest [2048];
+ dest[0] = 0;
+ GetSystemDirectoryW (dest, (UINT) numElementsInArray (dest));
+ return File (String (dest));
+ }
+
+ case invokedExecutableFile:
+ case currentExecutableFile:
+ case currentApplicationFile:
+ return WindowsFileHelpers::getModuleFileName ((HINSTANCE) Process::getCurrentModuleInstanceHandle());
+
+ case hostApplicationPath:
+ return WindowsFileHelpers::getModuleFileName (0);
+
+ default:
+ jassertfalse; // unknown type?
+ return File();
+ }
+
+ return WindowsFileHelpers::getSpecialFolderPath (csidlType);
+}
+
+//==============================================================================
+File File::getCurrentWorkingDirectory()
+{
+ WCHAR dest [MAX_PATH + 256];
+ dest[0] = 0;
+ GetCurrentDirectory ((DWORD) numElementsInArray (dest), dest);
+ return File (String (dest));
+}
+
+bool File::setAsCurrentWorkingDirectory() const
+{
+ return SetCurrentDirectory (getFullPathName().toWideCharPointer()) != FALSE;
+}
+
+//==============================================================================
+String File::getVersion() const
+{
+ String result;
+
+ DWORD handle = 0;
+ DWORD bufferSize = GetFileVersionInfoSize (getFullPathName().toWideCharPointer(), &handle);
+ HeapBlock<char> buffer;
+ buffer.calloc (bufferSize);
+
+ if (GetFileVersionInfo (getFullPathName().toWideCharPointer(), 0, bufferSize, buffer))
+ {
+ VS_FIXEDFILEINFO* vffi;
+ UINT len = 0;
+
+ if (VerQueryValue (buffer, (LPTSTR) _T("\\"), (LPVOID*) &vffi, &len))
+ {
+ result << (int) HIWORD (vffi->dwFileVersionMS) << '.'
+ << (int) LOWORD (vffi->dwFileVersionMS) << '.'
+ << (int) HIWORD (vffi->dwFileVersionLS) << '.'
+ << (int) LOWORD (vffi->dwFileVersionLS);
+ }
+ }
+
+ return result;
+}
+
+//==============================================================================
+bool File::isLink() const
+{
+ return hasFileExtension (".lnk");
+}
+
+File File::getLinkedTarget() const
+{
+ File result (*this);
+ String p (getFullPathName());
+
+ if (! exists())
+ p += ".lnk";
+ else if (! hasFileExtension (".lnk"))
+ return result;
+
+ ComSmartPtr<IShellLink> shellLink;
+ ComSmartPtr<IPersistFile> persistFile;
+
+ if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
+ && SUCCEEDED (shellLink.QueryInterface (persistFile))
+ && SUCCEEDED (persistFile->Load (p.toWideCharPointer(), STGM_READ))
+ && SUCCEEDED (shellLink->Resolve (0, SLR_ANY_MATCH | SLR_NO_UI)))
+ {
+ WIN32_FIND_DATA winFindData;
+ WCHAR resolvedPath [MAX_PATH];
+
+ if (SUCCEEDED (shellLink->GetPath (resolvedPath, MAX_PATH, &winFindData, SLGP_UNCPRIORITY)))
+ result = File (resolvedPath);
+ }
+
+ return result;
+}
+
+bool File::createLink (const String& description, const File& linkFileToCreate) const
+{
+ linkFileToCreate.deleteFile();
+
+ ComSmartPtr<IShellLink> shellLink;
+ ComSmartPtr<IPersistFile> persistFile;
+
+ CoInitialize (0);
+
+ return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
+ && SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer()))
+ && SUCCEEDED (shellLink->SetDescription (description.toWideCharPointer()))
+ && SUCCEEDED (shellLink.QueryInterface (persistFile))
+ && SUCCEEDED (persistFile->Save (linkFileToCreate.getFullPathName().toWideCharPointer(), TRUE));
+}
+
+//==============================================================================
+class DirectoryIterator::NativeIterator::Pimpl
+{
+public:
+ Pimpl (const File& directory, const String& wildCard)
+ : directoryWithWildCard (File::addTrailingSeparator (directory.getFullPathName()) + wildCard),
+ handle (INVALID_HANDLE_VALUE)
+ {
+ }
+
+ ~Pimpl()
+ {
+ if (handle != INVALID_HANDLE_VALUE)
+ FindClose (handle);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ using namespace WindowsFileHelpers;
+ WIN32_FIND_DATA findData;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ handle = FindFirstFile (directoryWithWildCard.toWideCharPointer(), &findData);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return false;
+ }
+ else
+ {
+ if (FindNextFile (handle, &findData) == 0)
+ return false;
+ }
+
+ filenameFound = findData.cFileName;
+
+ if (isDir != nullptr) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ if (isHidden != nullptr) *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
+ if (isReadOnly != nullptr) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
+ if (fileSize != nullptr) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
+ if (modTime != nullptr) *modTime = Time (fileTimeToTime (&findData.ftLastWriteTime));
+ if (creationTime != nullptr) *creationTime = Time (fileTimeToTime (&findData.ftCreationTime));
+
+ return true;
+ }
+
+private:
+ const String directoryWithWildCard;
+ HANDLE handle;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
+{
+}
+
+DirectoryIterator::NativeIterator::~NativeIterator()
+{
+}
+
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
+}
+
+
+//==============================================================================
+bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters)
+{
+ HINSTANCE hInstance = 0;
+
+ JUCE_TRY
+ {
+ hInstance = ShellExecute (0, 0, fileName.toWideCharPointer(),
+ parameters.toWideCharPointer(), 0, SW_SHOWDEFAULT);
+ }
+ JUCE_CATCH_ALL
+
+ return hInstance > (HINSTANCE) 32;
+}
+
+void File::revealToUser() const
+{
+ DynamicLibrary dll ("Shell32.dll");
+ JUCE_LOAD_WINAPI_FUNCTION (dll, ILCreateFromPathW, ilCreateFromPathW, ITEMIDLIST*, (LPCWSTR))
+ JUCE_LOAD_WINAPI_FUNCTION (dll, ILFree, ilFree, void, (ITEMIDLIST*))
+ JUCE_LOAD_WINAPI_FUNCTION (dll, SHOpenFolderAndSelectItems, shOpenFolderAndSelectItems, HRESULT, (ITEMIDLIST*, UINT, void*, DWORD))
+
+ if (ilCreateFromPathW != nullptr && shOpenFolderAndSelectItems != nullptr && ilFree != nullptr)
+ {
+ if (ITEMIDLIST* const itemIDList = ilCreateFromPathW (fullPath.toWideCharPointer()))
+ {
+ shOpenFolderAndSelectItems (itemIDList, 0, nullptr, 0);
+ ilFree (itemIDList);
+ }
+ }
+}
+
+//==============================================================================
+class NamedPipe::Pimpl
+{
+public:
+ Pimpl (const String& pipeName, const bool createPipe)
+ : filename ("\\\\.\\pipe\\" + File::createLegalFileName (pipeName)),
+ pipeH (INVALID_HANDLE_VALUE),
+ cancelEvent (CreateEvent (0, FALSE, FALSE, 0)),
+ connected (false), ownsPipe (createPipe), shouldStop (false)
+ {
+ if (createPipe)
+ pipeH = CreateNamedPipe (filename.toWideCharPointer(),
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
+ PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, 0);
+ }
+
+ ~Pimpl()
+ {
+ disconnectPipe();
+
+ if (pipeH != INVALID_HANDLE_VALUE)
+ CloseHandle (pipeH);
+
+ CloseHandle (cancelEvent);
+ }
+
+ bool connect (const int timeOutMs)
+ {
+ if (! ownsPipe)
+ {
+ if (pipeH != INVALID_HANDLE_VALUE)
+ return true;
+
+ const Time timeOutEnd (Time::getCurrentTime() + RelativeTime::milliseconds (timeOutMs));
+
+ for (;;)
+ {
+ {
+ const ScopedLock sl (createFileLock);
+
+ if (pipeH == INVALID_HANDLE_VALUE)
+ pipeH = CreateFile (filename.toWideCharPointer(),
+ GENERIC_READ | GENERIC_WRITE, 0, 0,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+ }
+
+ if (pipeH != INVALID_HANDLE_VALUE)
+ return true;
+
+ if (shouldStop || (timeOutMs >= 0 && Time::getCurrentTime() > timeOutEnd))
+ return false;
+
+ Thread::sleep (1);
+ }
+ }
+
+ if (! connected)
+ {
+ OverlappedEvent over;
+
+ if (ConnectNamedPipe (pipeH, &over.over) == 0)
+ {
+ switch (GetLastError())
+ {
+ case ERROR_PIPE_CONNECTED: connected = true; break;
+ case ERROR_IO_PENDING:
+ case ERROR_PIPE_LISTENING: connected = waitForIO (over, timeOutMs); break;
+ default: break;
+ }
+ }
+ }
+
+ return connected;
+ }
+
+ void disconnectPipe()
+ {
+ if (ownsPipe && connected)
+ {
+ DisconnectNamedPipe (pipeH);
+ connected = false;
+ }
+ }
+
+ int read (void* destBuffer, const int maxBytesToRead, const int timeOutMilliseconds)
+ {
+ while (connect (timeOutMilliseconds))
+ {
+ if (maxBytesToRead <= 0)
+ return 0;
+
+ OverlappedEvent over;
+ unsigned long numRead;
+
+ if (ReadFile (pipeH, destBuffer, (DWORD) maxBytesToRead, &numRead, &over.over))
+ return (int) numRead;
+
+ const DWORD lastError = GetLastError();
+
+ if (lastError == ERROR_IO_PENDING)
+ {
+ if (! waitForIO (over, timeOutMilliseconds))
+ return -1;
+
+ if (GetOverlappedResult (pipeH, &over.over, &numRead, FALSE))
+ return (int) numRead;
+ }
+
+ if (ownsPipe && (GetLastError() == ERROR_BROKEN_PIPE || GetLastError() == ERROR_PIPE_NOT_CONNECTED))
+ disconnectPipe();
+ else
+ break;
+ }
+
+ return -1;
+ }
+
+ int write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
+ {
+ if (connect (timeOutMilliseconds))
+ {
+ if (numBytesToWrite <= 0)
+ return 0;
+
+ OverlappedEvent over;
+ unsigned long numWritten;
+
+ if (WriteFile (pipeH, sourceBuffer, (DWORD) numBytesToWrite, &numWritten, &over.over))
+ return (int) numWritten;
+
+ if (GetLastError() == ERROR_IO_PENDING)
+ {
+ if (! waitForIO (over, timeOutMilliseconds))
+ return -1;
+
+ if (GetOverlappedResult (pipeH, &over.over, &numWritten, FALSE))
+ return (int) numWritten;
+
+ if (GetLastError() == ERROR_BROKEN_PIPE && ownsPipe)
+ disconnectPipe();
+ }
+ }
+
+ return -1;
+ }
+
+ const String filename;
+ HANDLE pipeH, cancelEvent;
+ bool connected, ownsPipe, shouldStop;
+ CriticalSection createFileLock;
+
+private:
+ struct OverlappedEvent
+ {
+ OverlappedEvent()
+ {
+ zerostruct (over);
+ over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
+ }
+
+ ~OverlappedEvent()
+ {
+ CloseHandle (over.hEvent);
+ }
+
+ OVERLAPPED over;
+ };
+
+ bool waitForIO (OverlappedEvent& over, int timeOutMilliseconds)
+ {
+ if (shouldStop)
+ return false;
+
+ HANDLE handles[] = { over.over.hEvent, cancelEvent };
+ DWORD waitResult = WaitForMultipleObjects (2, handles, FALSE,
+ timeOutMilliseconds >= 0 ? timeOutMilliseconds
+ : INFINITE);
+
+ if (waitResult == WAIT_OBJECT_0)
+ return true;
+
+ CancelIo (pipeH);
+ return false;
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
+};
+
+void NamedPipe::close()
+{
+ if (pimpl != nullptr)
+ {
+ pimpl->shouldStop = true;
+ SetEvent (pimpl->cancelEvent);
+
+ ScopedWriteLock sl (lock);
+ pimpl = nullptr;
+ }
+}
+
+bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
+{
+ pimpl = new Pimpl (pipeName, createPipe);
+
+ if (createPipe && pimpl->pipeH == INVALID_HANDLE_VALUE)
+ {
+ pimpl = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
+{
+ ScopedReadLock sl (lock);
+ return pimpl != nullptr ? pimpl->read (destBuffer, maxBytesToRead, timeOutMilliseconds) : -1;
+}
+
+int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
+{
+ ScopedReadLock sl (lock);
+ return pimpl != nullptr ? pimpl->write (sourceBuffer, numBytesToWrite, timeOutMilliseconds) : -1;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Network.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Network.cpp
new file mode 100644
index 0000000..1b35453
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Network.cpp
@@ -0,0 +1,486 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef INTERNET_FLAG_NEED_FILE
+ #define INTERNET_FLAG_NEED_FILE 0x00000010
+#endif
+
+#ifndef INTERNET_OPTION_DISABLE_AUTODIAL
+ #define INTERNET_OPTION_DISABLE_AUTODIAL 70
+#endif
+
+//==============================================================================
+class WebInputStream : public InputStream
+{
+public:
+ WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
+ : statusCode (0), connection (0), request (0),
+ address (address_), headers (headers_), postData (postData_), position (0),
+ finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
+ {
+ createConnection (progressCallback, progressCallbackContext);
+
+ if (! isError())
+ {
+ if (responseHeaders != nullptr)
+ {
+ DWORD bufferSizeBytes = 4096;
+
+ for (;;)
+ {
+ HeapBlock<char> buffer ((size_t) bufferSizeBytes);
+
+ if (HttpQueryInfo (request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer.getData(), &bufferSizeBytes, 0))
+ {
+ StringArray headersArray;
+ headersArray.addLines (String (reinterpret_cast<const WCHAR*> (buffer.getData())));
+
+ for (int i = 0; i < headersArray.size(); ++i)
+ {
+ const String& header = headersArray[i];
+ const String key (header.upToFirstOccurrenceOf (": ", false, false));
+ const String value (header.fromFirstOccurrenceOf (": ", false, false));
+ const String previousValue ((*responseHeaders) [key]);
+
+ responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
+ }
+
+ break;
+ }
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ break;
+ }
+ }
+
+ DWORD status = 0;
+ DWORD statusSize = sizeof (status);
+
+ if (HttpQueryInfo (request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &statusSize, 0))
+ statusCode = (int) status;
+ }
+ }
+
+ ~WebInputStream()
+ {
+ close();
+ }
+
+ //==============================================================================
+ bool isError() const { return request == 0; }
+ bool isExhausted() { return finished; }
+ int64 getPosition() { return position; }
+
+ int64 getTotalLength()
+ {
+ if (! isError())
+ {
+ DWORD index = 0, result = 0, size = sizeof (result);
+
+ if (HttpQueryInfo (request, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &result, &size, &index))
+ return (int64) result;
+ }
+
+ return -1;
+ }
+
+ int read (void* buffer, int bytesToRead)
+ {
+ jassert (buffer != nullptr && bytesToRead >= 0);
+ DWORD bytesRead = 0;
+
+ if (! (finished || isError()))
+ {
+ InternetReadFile (request, buffer, (DWORD) bytesToRead, &bytesRead);
+ position += bytesRead;
+
+ if (bytesRead == 0)
+ finished = true;
+ }
+
+ return (int) bytesRead;
+ }
+
+ bool setPosition (int64 wantedPos)
+ {
+ if (isError())
+ return false;
+
+ if (wantedPos != position)
+ {
+ finished = false;
+ position = (int64) InternetSetFilePointer (request, (LONG) wantedPos, 0, FILE_BEGIN, 0);
+
+ if (position == wantedPos)
+ return true;
+
+ if (wantedPos < position)
+ {
+ close();
+ position = 0;
+ createConnection (0, 0);
+ }
+
+ skipNextBytes (wantedPos - position);
+ }
+
+ return true;
+ }
+
+ int statusCode;
+
+private:
+ //==============================================================================
+ HINTERNET connection, request;
+ String address, headers;
+ MemoryBlock postData;
+ int64 position;
+ bool finished;
+ const bool isPost;
+ int timeOutMs;
+
+ void close()
+ {
+ if (request != 0)
+ {
+ InternetCloseHandle (request);
+ request = 0;
+ }
+
+ if (connection != 0)
+ {
+ InternetCloseHandle (connection);
+ connection = 0;
+ }
+ }
+
+ void createConnection (URL::OpenStreamProgressCallback* progressCallback,
+ void* progressCallbackContext)
+ {
+ static HINTERNET sessionHandle = InternetOpen (_T("juce"), INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
+
+ close();
+
+ if (sessionHandle != 0)
+ {
+ // break up the url..
+ const int fileNumChars = 65536;
+ const int serverNumChars = 2048;
+ const int usernameNumChars = 1024;
+ const int passwordNumChars = 1024;
+ HeapBlock<TCHAR> file (fileNumChars), server (serverNumChars),
+ username (usernameNumChars), password (passwordNumChars);
+
+ URL_COMPONENTS uc = { 0 };
+ uc.dwStructSize = sizeof (uc);
+ uc.lpszUrlPath = file;
+ uc.dwUrlPathLength = fileNumChars;
+ uc.lpszHostName = server;
+ uc.dwHostNameLength = serverNumChars;
+ uc.lpszUserName = username;
+ uc.dwUserNameLength = usernameNumChars;
+ uc.lpszPassword = password;
+ uc.dwPasswordLength = passwordNumChars;
+
+ if (InternetCrackUrl (address.toWideCharPointer(), 0, 0, &uc))
+ openConnection (uc, sessionHandle, progressCallback, progressCallbackContext);
+ }
+ }
+
+ void openConnection (URL_COMPONENTS& uc, HINTERNET sessionHandle,
+ URL::OpenStreamProgressCallback* progressCallback,
+ void* progressCallbackContext)
+ {
+ int disable = 1;
+ InternetSetOption (sessionHandle, INTERNET_OPTION_DISABLE_AUTODIAL, &disable, sizeof (disable));
+
+ if (timeOutMs == 0)
+ timeOutMs = 30000;
+ else if (timeOutMs < 0)
+ timeOutMs = -1;
+
+ applyTimeout (sessionHandle, INTERNET_OPTION_CONNECT_TIMEOUT);
+ applyTimeout (sessionHandle, INTERNET_OPTION_RECEIVE_TIMEOUT);
+ applyTimeout (sessionHandle, INTERNET_OPTION_SEND_TIMEOUT);
+ applyTimeout (sessionHandle, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT);
+ applyTimeout (sessionHandle, INTERNET_OPTION_DATA_SEND_TIMEOUT);
+
+ const bool isFtp = address.startsWithIgnoreCase ("ftp:");
+
+ connection = InternetConnect (sessionHandle, uc.lpszHostName, uc.nPort,
+ uc.lpszUserName, uc.lpszPassword,
+ isFtp ? (DWORD) INTERNET_SERVICE_FTP
+ : (DWORD) INTERNET_SERVICE_HTTP,
+ 0, 0);
+ if (connection != 0)
+ {
+ if (isFtp)
+ request = FtpOpenFile (connection, uc.lpszUrlPath, GENERIC_READ,
+ FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_NEED_FILE, 0);
+ else
+ openHTTPConnection (uc, progressCallback, progressCallbackContext);
+ }
+ }
+
+ void applyTimeout (HINTERNET sessionHandle, const DWORD option)
+ {
+ InternetSetOption (sessionHandle, option, &timeOutMs, sizeof (timeOutMs));
+ }
+
+ void openHTTPConnection (URL_COMPONENTS& uc, URL::OpenStreamProgressCallback* progressCallback,
+ void* progressCallbackContext)
+ {
+ const TCHAR* mimeTypes[] = { _T("*/*"), nullptr };
+
+ DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES
+ | INTERNET_FLAG_NO_AUTO_REDIRECT | SECURITY_SET_MASK;
+
+ if (address.startsWithIgnoreCase ("https:"))
+ flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 -
+ // IE7 seems to automatically work out when it's https)
+
+ request = HttpOpenRequest (connection, isPost ? _T("POST") : _T("GET"),
+ uc.lpszUrlPath, 0, 0, mimeTypes, flags, 0);
+
+ if (request != 0)
+ {
+ setSecurityFlags();
+
+ INTERNET_BUFFERS buffers = { 0 };
+ buffers.dwStructSize = sizeof (INTERNET_BUFFERS);
+ buffers.lpcszHeader = headers.toWideCharPointer();
+ buffers.dwHeadersLength = (DWORD) headers.length();
+ buffers.dwBufferTotal = (DWORD) postData.getSize();
+
+ if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0))
+ {
+ int bytesSent = 0;
+
+ for (;;)
+ {
+ const int bytesToDo = jmin (1024, (int) postData.getSize() - bytesSent);
+ DWORD bytesDone = 0;
+
+ if (bytesToDo > 0
+ && ! InternetWriteFile (request,
+ static_cast<const char*> (postData.getData()) + bytesSent,
+ (DWORD) bytesToDo, &bytesDone))
+ {
+ break;
+ }
+
+ if (bytesToDo == 0 || (int) bytesDone < bytesToDo)
+ {
+ if (HttpEndRequest (request, 0, 0, 0))
+ return;
+
+ break;
+ }
+
+ bytesSent += bytesDone;
+
+ if (progressCallback != nullptr
+ && ! progressCallback (progressCallbackContext, bytesSent, (int) postData.getSize()))
+ break;
+ }
+ }
+ }
+
+ close();
+ }
+
+ void setSecurityFlags()
+ {
+ DWORD dwFlags = 0, dwBuffLen = sizeof (DWORD);
+ InternetQueryOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen);
+ dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_SET_MASK;
+ InternetSetOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags));
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
+};
+
+
+//==============================================================================
+struct GetAdaptersInfoHelper
+{
+ bool callGetAdaptersInfo()
+ {
+ DynamicLibrary dll ("iphlpapi.dll");
+ JUCE_LOAD_WINAPI_FUNCTION (dll, GetAdaptersInfo, getAdaptersInfo, DWORD, (PIP_ADAPTER_INFO, PULONG))
+
+ if (getAdaptersInfo == nullptr)
+ return false;
+
+ adapterInfo.malloc (1);
+ ULONG len = sizeof (IP_ADAPTER_INFO);
+
+ if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW)
+ adapterInfo.malloc (len, 1);
+
+ return getAdaptersInfo (adapterInfo, &len) == NO_ERROR;
+ }
+
+ HeapBlock<IP_ADAPTER_INFO> adapterInfo;
+};
+
+namespace MACAddressHelpers
+{
+ static void addAddress (Array<MACAddress>& result, const MACAddress& ma)
+ {
+ if (! ma.isNull())
+ result.addIfNotAlreadyThere (ma);
+ }
+
+ static void getViaGetAdaptersInfo (Array<MACAddress>& result)
+ {
+ GetAdaptersInfoHelper gah;
+
+ if (gah.callGetAdaptersInfo())
+ {
+ for (PIP_ADAPTER_INFO adapter = gah.adapterInfo; adapter != nullptr; adapter = adapter->Next)
+ if (adapter->AddressLength >= 6)
+ addAddress (result, MACAddress (adapter->Address));
+ }
+ }
+
+ static void getViaNetBios (Array<MACAddress>& result)
+ {
+ DynamicLibrary dll ("netapi32.dll");
+ JUCE_LOAD_WINAPI_FUNCTION (dll, Netbios, NetbiosCall, UCHAR, (PNCB))
+
+ if (NetbiosCall != 0)
+ {
+ LANA_ENUM enums = { 0 };
+
+ {
+ NCB ncb = { 0 };
+ ncb.ncb_command = NCBENUM;
+ ncb.ncb_buffer = (unsigned char*) &enums;
+ ncb.ncb_length = sizeof (LANA_ENUM);
+ NetbiosCall (&ncb);
+ }
+
+ for (int i = 0; i < enums.length; ++i)
+ {
+ NCB ncb2 = { 0 };
+ ncb2.ncb_command = NCBRESET;
+ ncb2.ncb_lana_num = enums.lana[i];
+
+ if (NetbiosCall (&ncb2) == 0)
+ {
+ NCB ncb = { 0 };
+ memcpy (ncb.ncb_callname, "* ", NCBNAMSZ);
+ ncb.ncb_command = NCBASTAT;
+ ncb.ncb_lana_num = enums.lana[i];
+
+ struct ASTAT
+ {
+ ADAPTER_STATUS adapt;
+ NAME_BUFFER NameBuff [30];
+ };
+
+ ASTAT astat;
+ zerostruct (astat);
+ ncb.ncb_buffer = (unsigned char*) &astat;
+ ncb.ncb_length = sizeof (ASTAT);
+
+ if (NetbiosCall (&ncb) == 0 && astat.adapt.adapter_type == 0xfe)
+ addAddress (result, MACAddress (astat.adapt.adapter_address));
+ }
+ }
+ }
+ }
+}
+
+void MACAddress::findAllAddresses (Array<MACAddress>& result)
+{
+ MACAddressHelpers::getViaGetAdaptersInfo (result);
+ MACAddressHelpers::getViaNetBios (result);
+}
+
+void IPAddress::findAllAddresses (Array<IPAddress>& result)
+{
+ result.addIfNotAlreadyThere (IPAddress::local());
+
+ GetAdaptersInfoHelper gah;
+
+ if (gah.callGetAdaptersInfo())
+ {
+ for (PIP_ADAPTER_INFO adapter = gah.adapterInfo; adapter != nullptr; adapter = adapter->Next)
+ {
+ IPAddress ip (adapter->IpAddressList.IpAddress.String);
+
+ if (ip != IPAddress::any())
+ result.addIfNotAlreadyThere (ip);
+ }
+ }
+}
+
+//==============================================================================
+bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailAddress,
+ const String& emailSubject,
+ const String& bodyText,
+ const StringArray& filesToAttach)
+{
+ DynamicLibrary dll ("MAPI32.dll");
+ JUCE_LOAD_WINAPI_FUNCTION (dll, MAPISendMail, mapiSendMail,
+ ULONG, (LHANDLE, ULONG, lpMapiMessage, ::FLAGS, ULONG))
+
+ if (mapiSendMail == nullptr)
+ return false;
+
+ MapiMessage message = { 0 };
+ message.lpszSubject = (LPSTR) emailSubject.toRawUTF8();
+ message.lpszNoteText = (LPSTR) bodyText.toRawUTF8();
+
+ MapiRecipDesc recip = { 0 };
+ recip.ulRecipClass = MAPI_TO;
+ String targetEmailAddress_ (targetEmailAddress);
+ if (targetEmailAddress_.isEmpty())
+ targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address)
+ recip.lpszName = (LPSTR) targetEmailAddress_.toRawUTF8();
+ message.nRecipCount = 1;
+ message.lpRecips = &recip;
+
+ HeapBlock <MapiFileDesc> files;
+ files.calloc ((size_t) filesToAttach.size());
+
+ message.nFileCount = (ULONG) filesToAttach.size();
+ message.lpFiles = files;
+
+ for (int i = 0; i < filesToAttach.size(); ++i)
+ {
+ files[i].nPosition = (ULONG) -1;
+ files[i].lpszPathName = (LPSTR) filesToAttach[i].toRawUTF8();
+ }
+
+ return mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Registry.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Registry.cpp
new file mode 100644
index 0000000..8119474
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Registry.cpp
@@ -0,0 +1,227 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+struct RegistryKeyWrapper
+{
+ RegistryKeyWrapper (String name, const bool createForWriting, const DWORD wow64Flags)
+ : key (0), wideCharValueName (nullptr)
+ {
+ HKEY rootKey = 0;
+
+ if (name.startsWithIgnoreCase ("HKEY_CURRENT_USER\\")) rootKey = HKEY_CURRENT_USER;
+ else if (name.startsWithIgnoreCase ("HKEY_LOCAL_MACHINE\\")) rootKey = HKEY_LOCAL_MACHINE;
+ else if (name.startsWithIgnoreCase ("HKEY_CLASSES_ROOT\\")) rootKey = HKEY_CLASSES_ROOT;
+
+ if (rootKey != 0)
+ {
+ name = name.substring (name.indexOfChar ('\\') + 1);
+
+ const int lastSlash = name.lastIndexOfChar ('\\');
+ valueName = name.substring (lastSlash + 1);
+ wideCharValueName = valueName.toWideCharPointer();
+
+ name = name.substring (0, lastSlash);
+ const wchar_t* const wideCharName = name.toWideCharPointer();
+ DWORD result;
+
+ if (createForWriting)
+ RegCreateKeyEx (rootKey, wideCharName, 0, 0, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE | KEY_QUERY_VALUE | wow64Flags, 0, &key, &result);
+ else
+ RegOpenKeyEx (rootKey, wideCharName, 0, KEY_READ | wow64Flags, &key);
+ }
+ }
+
+ ~RegistryKeyWrapper()
+ {
+ if (key != 0)
+ RegCloseKey (key);
+ }
+
+ static bool setValue (const String& regValuePath, const DWORD type,
+ const void* data, size_t dataSize, const DWORD wow64Flags)
+ {
+ const RegistryKeyWrapper key (regValuePath, true, wow64Flags);
+
+ return key.key != 0
+ && RegSetValueEx (key.key, key.wideCharValueName, 0, type,
+ reinterpret_cast <const BYTE*> (data),
+ (DWORD) dataSize) == ERROR_SUCCESS;
+ }
+
+ static uint32 getBinaryValue (const String& regValuePath, MemoryBlock& result, DWORD wow64Flags)
+ {
+ const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
+
+ if (key.key != 0)
+ {
+ for (unsigned long bufferSize = 1024; ; bufferSize *= 2)
+ {
+ result.setSize (bufferSize, false);
+ DWORD type = REG_NONE;
+
+ const LONG err = RegQueryValueEx (key.key, key.wideCharValueName, 0, &type,
+ (LPBYTE) result.getData(), &bufferSize);
+
+ if (err == ERROR_SUCCESS)
+ {
+ result.setSize (bufferSize, false);
+ return type;
+ }
+
+ if (err != ERROR_MORE_DATA)
+ break;
+ }
+ }
+
+ return REG_NONE;
+ }
+
+ static String getValue (const String& regValuePath, const String& defaultValue, DWORD wow64Flags)
+ {
+ MemoryBlock buffer;
+ switch (getBinaryValue (regValuePath, buffer, wow64Flags))
+ {
+ case REG_SZ: return static_cast <const WCHAR*> (buffer.getData());
+ case REG_DWORD: return String ((int) *reinterpret_cast<const DWORD*> (buffer.getData()));
+ default: break;
+ }
+
+ return defaultValue;
+ }
+
+ static bool keyExists (const String& regValuePath, const DWORD wow64Flags)
+ {
+ return RegistryKeyWrapper (regValuePath, false, wow64Flags).key != 0;
+ }
+
+ static bool valueExists (const String& regValuePath, const DWORD wow64Flags)
+ {
+ const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
+
+ if (key.key == 0)
+ return false;
+
+ unsigned char buffer [512];
+ unsigned long bufferSize = sizeof (buffer);
+ DWORD type = 0;
+
+ const LONG result = RegQueryValueEx (key.key, key.wideCharValueName,
+ 0, &type, buffer, &bufferSize);
+
+ return result == ERROR_SUCCESS || result == ERROR_MORE_DATA;
+ }
+
+ HKEY key;
+ const wchar_t* wideCharValueName;
+ String valueName;
+
+ JUCE_DECLARE_NON_COPYABLE (RegistryKeyWrapper)
+};
+
+uint32 JUCE_CALLTYPE WindowsRegistry::getBinaryValue (const String& regValuePath, MemoryBlock& result, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::getBinaryValue (regValuePath, result, (DWORD) mode);
+}
+
+String JUCE_CALLTYPE WindowsRegistry::getValue (const String& regValuePath, const String& defaultValue, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::getValue (regValuePath, defaultValue, (DWORD) mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const String& value, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::setValue (regValuePath, REG_SZ, value.toWideCharPointer(),
+ CharPointer_UTF16::getBytesRequiredFor (value.getCharPointer()), mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const uint32 value, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::setValue (regValuePath, REG_DWORD, &value, sizeof (value), (DWORD) mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const uint64 value, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::setValue (regValuePath, REG_QWORD, &value, sizeof (value), (DWORD) mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const MemoryBlock& value, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::setValue (regValuePath, REG_BINARY, value.getData(), value.getSize(), (DWORD) mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::valueExists (const String& regValuePath, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::valueExists (regValuePath, (DWORD) mode);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::keyExists (const String& regValuePath, WoW64Mode mode)
+{
+ return RegistryKeyWrapper::keyExists (regValuePath, (DWORD) mode);
+}
+
+void JUCE_CALLTYPE WindowsRegistry::deleteValue (const String& regValuePath, WoW64Mode mode)
+{
+ const RegistryKeyWrapper key (regValuePath, true, (DWORD) mode);
+
+ if (key.key != 0)
+ RegDeleteValue (key.key, key.wideCharValueName);
+}
+
+void JUCE_CALLTYPE WindowsRegistry::deleteKey (const String& regKeyPath, WoW64Mode mode)
+{
+ const RegistryKeyWrapper key (regKeyPath, true, (DWORD) mode);
+
+ if (key.key != 0)
+ RegDeleteKey (key.key, key.wideCharValueName);
+}
+
+bool JUCE_CALLTYPE WindowsRegistry::registerFileAssociation (const String& fileExtension,
+ const String& symbolicDescription,
+ const String& fullDescription,
+ const File& targetExecutable,
+ const int iconResourceNumber,
+ const bool registerForCurrentUserOnly,
+ WoW64Mode mode)
+{
+ const char* const root = registerForCurrentUserOnly ? "HKEY_CURRENT_USER\\Software\\Classes\\"
+ : "HKEY_CLASSES_ROOT\\";
+ const String key (root + symbolicDescription);
+
+ return setValue (root + fileExtension + "\\", symbolicDescription, mode)
+ && setValue (key + "\\", fullDescription, mode)
+ && setValue (key + "\\shell\\open\\command\\", targetExecutable.getFullPathName() + " \"%1\"", mode)
+ && (iconResourceNumber == 0
+ || setValue (key + "\\DefaultIcon\\",
+ targetExecutable.getFullPathName() + "," + String (iconResourceNumber)));
+}
+
+// These methods are deprecated:
+String WindowsRegistry::getValueWow64 (const String& p, const String& defVal) { return getValue (p, defVal, WoW64_64bit); }
+bool WindowsRegistry::valueExistsWow64 (const String& p) { return valueExists (p, WoW64_64bit); }
+bool WindowsRegistry::keyExistsWow64 (const String& p) { return keyExists (p, WoW64_64bit); }
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_SystemStats.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_SystemStats.cpp
new file mode 100644
index 0000000..901bc76
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_SystemStats.cpp
@@ -0,0 +1,459 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+void Logger::outputDebugString (const String& text)
+{
+ OutputDebugString ((text + "\n").toWideCharPointer());
+}
+
+//==============================================================================
+#ifdef JUCE_DLL_BUILD
+ JUCE_API void* juceDLL_malloc (size_t sz) { return std::malloc (sz); }
+ JUCE_API void juceDLL_free (void* block) { std::free (block); }
+#endif
+
+//==============================================================================
+#if JUCE_USE_INTRINSICS
+
+// CPU info functions using intrinsics...
+
+#pragma intrinsic (__cpuid)
+#pragma intrinsic (__rdtsc)
+
+static void callCPUID (int result[4], int infoType)
+{
+ __cpuid (result, infoType);
+}
+
+#else
+
+static void callCPUID (int result[4], int infoType)
+{
+ #if ! JUCE_MINGW
+ __try
+ #endif
+ {
+ #if JUCE_GCC
+ __asm__ __volatile__ ("cpuid" : "=a" (result[0]), "=b" (result[1]), "=c" (result[2]),"=d" (result[3]) : "a" (infoType));
+ #else
+ __asm
+ {
+ mov esi, result
+ mov eax, infoType
+ xor ecx, ecx
+ cpuid
+ mov dword ptr [esi + 0], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ }
+ #endif
+ }
+ #if ! JUCE_MINGW
+ __except (EXCEPTION_EXECUTE_HANDLER) {}
+ #endif
+}
+
+#endif
+
+String SystemStats::getCpuVendor()
+{
+ int info[4] = { 0 };
+ callCPUID (info, 0);
+
+ char v [12];
+ memcpy (v, info + 1, 4);
+ memcpy (v + 4, info + 3, 4);
+ memcpy (v + 8, info + 2, 4);
+
+ return String (v, 12);
+}
+
+//==============================================================================
+void CPUInformation::initialise() noexcept
+{
+ int info[4] = { 0 };
+ callCPUID (info, 1);
+
+ // NB: IsProcessorFeaturePresent doesn't work on XP
+ hasMMX = (info[3] & (1 << 23)) != 0;
+ hasSSE = (info[3] & (1 << 25)) != 0;
+ hasSSE2 = (info[3] & (1 << 26)) != 0;
+ hasSSE3 = (info[2] & (1 << 0)) != 0;
+ has3DNow = (info[1] & (1 << 31)) != 0;
+
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo (&systemInfo);
+ numCpus = (int) systemInfo.dwNumberOfProcessors;
+}
+
+#if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
+struct DebugFlagsInitialiser
+{
+ DebugFlagsInitialiser()
+ {
+ _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ }
+};
+
+static DebugFlagsInitialiser debugFlagsInitialiser;
+#endif
+
+//==============================================================================
+static bool isWindowsVersionOrLater (SystemStats::OperatingSystemType target)
+{
+ OSVERSIONINFOEX info;
+ zerostruct (info);
+ info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
+
+ if (target >= SystemStats::WinVista)
+ {
+ info.dwMajorVersion = 6;
+
+ switch (target)
+ {
+ case SystemStats::WinVista: break;
+ case SystemStats::Windows7: info.dwMinorVersion = 1; break;
+ case SystemStats::Windows8_0: info.dwMinorVersion = 2; break;
+ case SystemStats::Windows8_1: info.dwMinorVersion = 3; break;
+ default: jassertfalse; break;
+ }
+ }
+ else
+ {
+ info.dwMajorVersion = 5;
+ info.dwMinorVersion = target >= SystemStats::WinXP ? 1 : 0;
+ }
+
+ DWORDLONG mask = 0;
+
+ VER_SET_CONDITION (mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION (mask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION (mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ VER_SET_CONDITION (mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
+
+ return VerifyVersionInfo (&info,
+ VER_MAJORVERSION | VER_MINORVERSION
+ | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
+ mask) != FALSE;
+}
+
+SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
+{
+ const SystemStats::OperatingSystemType types[]
+ = { Windows8_1, Windows8_0, Windows7, WinVista, WinXP, Win2000 };
+
+ for (int i = 0; i < numElementsInArray (types); ++i)
+ if (isWindowsVersionOrLater (types[i]))
+ return types[i];
+
+ jassertfalse; // need to support whatever new version is running!
+ return UnknownOS;
+}
+
+String SystemStats::getOperatingSystemName()
+{
+ const char* name = "Unknown OS";
+
+ switch (getOperatingSystemType())
+ {
+ case Windows8_1: name = "Windows 8.1"; break;
+ case Windows8_0: name = "Windows 8.0"; break;
+ case Windows7: name = "Windows 7"; break;
+ case WinVista: name = "Windows Vista"; break;
+ case WinXP: name = "Windows XP"; break;
+ case Win2000: name = "Windows 2000"; break;
+ default: jassertfalse; break; // !! new type of OS?
+ }
+
+ return name;
+}
+
+String SystemStats::getDeviceDescription()
+{
+ return String();
+}
+
+bool SystemStats::isOperatingSystem64Bit()
+{
+ #if JUCE_64BIT
+ return true;
+ #else
+ typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+ LPFN_ISWOW64PROCESS fnIsWow64Process
+ = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandleA ("kernel32"), "IsWow64Process");
+
+ BOOL isWow64 = FALSE;
+
+ return fnIsWow64Process != nullptr
+ && fnIsWow64Process (GetCurrentProcess(), &isWow64)
+ && isWow64 != FALSE;
+ #endif
+}
+
+//==============================================================================
+int SystemStats::getMemorySizeInMegabytes()
+{
+ MEMORYSTATUSEX mem;
+ mem.dwLength = sizeof (mem);
+ GlobalMemoryStatusEx (&mem);
+ return (int) (mem.ullTotalPhys / (1024 * 1024)) + 1;
+}
+
+//==============================================================================
+String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
+{
+ DWORD len = GetEnvironmentVariableW (name.toWideCharPointer(), nullptr, 0);
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ return String (defaultValue);
+
+ HeapBlock<WCHAR> buffer (len);
+ len = GetEnvironmentVariableW (name.toWideCharPointer(), buffer, len);
+
+ return String (CharPointer_wchar_t (buffer),
+ CharPointer_wchar_t (buffer + len));
+}
+
+//==============================================================================
+uint32 juce_millisecondsSinceStartup() noexcept
+{
+ return (uint32) timeGetTime();
+}
+
+//==============================================================================
+class HiResCounterHandler
+{
+public:
+ HiResCounterHandler()
+ : hiResTicksOffset (0)
+ {
+ // This macro allows you to override the default timer-period
+ // used on Windows. By default this is set to 1, because that has
+ // always been the value used in JUCE apps, and changing it could
+ // affect the behaviour of existing code, but you may wish to make
+ // it larger (or set it to 0 to use the system default) to make your
+ // app less demanding on the CPU.
+ // For more info, see win32 documentation about the timeBeginPeriod
+ // function.
+ #ifndef JUCE_WIN32_TIMER_PERIOD
+ #define JUCE_WIN32_TIMER_PERIOD 1
+ #endif
+
+ #if JUCE_WIN32_TIMER_PERIOD > 0
+ const MMRESULT res = timeBeginPeriod (JUCE_WIN32_TIMER_PERIOD);
+ (void) res;
+ jassert (res == TIMERR_NOERROR);
+ #endif
+
+ LARGE_INTEGER f;
+ QueryPerformanceFrequency (&f);
+ hiResTicksPerSecond = f.QuadPart;
+ hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond;
+ }
+
+ inline int64 getHighResolutionTicks() noexcept
+ {
+ LARGE_INTEGER ticks;
+ QueryPerformanceCounter (&ticks);
+
+ const int64 mainCounterAsHiResTicks = (juce_millisecondsSinceStartup() * hiResTicksPerSecond) / 1000;
+ const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart;
+
+ // fix for a very obscure PCI hardware bug that can make the counter
+ // sometimes jump forwards by a few seconds..
+ const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset);
+
+ if (offsetDrift > (hiResTicksPerSecond >> 1))
+ hiResTicksOffset = newOffset;
+
+ return ticks.QuadPart + hiResTicksOffset;
+ }
+
+ inline double getMillisecondCounterHiRes() noexcept
+ {
+ return getHighResolutionTicks() * hiResTicksScaleFactor;
+ }
+
+ int64 hiResTicksPerSecond, hiResTicksOffset;
+ double hiResTicksScaleFactor;
+};
+
+static HiResCounterHandler hiResCounterHandler;
+
+int64 Time::getHighResolutionTicksPerSecond() noexcept { return hiResCounterHandler.hiResTicksPerSecond; }
+int64 Time::getHighResolutionTicks() noexcept { return hiResCounterHandler.getHighResolutionTicks(); }
+double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHandler.getMillisecondCounterHiRes(); }
+
+//==============================================================================
+static int64 juce_getClockCycleCounter() noexcept
+{
+ #if JUCE_USE_INTRINSICS
+ // MS intrinsics version...
+ return (int64) __rdtsc();
+
+ #elif JUCE_GCC
+ // GNU inline asm version...
+ unsigned int hi = 0, lo = 0;
+
+ __asm__ __volatile__ (
+ "xor %%eax, %%eax \n\
+ xor %%edx, %%edx \n\
+ rdtsc \n\
+ movl %%eax, %[lo] \n\
+ movl %%edx, %[hi]"
+ :
+ : [hi] "m" (hi),
+ [lo] "m" (lo)
+ : "cc", "eax", "ebx", "ecx", "edx", "memory");
+
+ return (int64) ((((uint64) hi) << 32) | lo);
+ #else
+ // MSVC inline asm version...
+ unsigned int hi = 0, lo = 0;
+
+ __asm
+ {
+ xor eax, eax
+ xor edx, edx
+ rdtsc
+ mov lo, eax
+ mov hi, edx
+ }
+
+ return (int64) ((((uint64) hi) << 32) | lo);
+ #endif
+}
+
+int SystemStats::getCpuSpeedInMegaherz()
+{
+ const int64 cycles = juce_getClockCycleCounter();
+ const uint32 millis = Time::getMillisecondCounter();
+ int lastResult = 0;
+
+ for (;;)
+ {
+ int n = 1000000;
+ while (--n > 0) {}
+
+ const uint32 millisElapsed = Time::getMillisecondCounter() - millis;
+ const int64 cyclesNow = juce_getClockCycleCounter();
+
+ if (millisElapsed > 80)
+ {
+ const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000);
+
+ if (millisElapsed > 500 || (lastResult == newResult && newResult > 100))
+ return newResult;
+
+ lastResult = newResult;
+ }
+ }
+}
+
+
+//==============================================================================
+bool Time::setSystemTimeToThisTime() const
+{
+ SYSTEMTIME st;
+
+ st.wDayOfWeek = 0;
+ st.wYear = (WORD) getYear();
+ st.wMonth = (WORD) (getMonth() + 1);
+ st.wDay = (WORD) getDayOfMonth();
+ st.wHour = (WORD) getHours();
+ st.wMinute = (WORD) getMinutes();
+ st.wSecond = (WORD) getSeconds();
+ st.wMilliseconds = (WORD) (millisSinceEpoch % 1000);
+
+ // do this twice because of daylight saving conversion problems - the
+ // first one sets it up, the second one kicks it in.
+ return SetLocalTime (&st) != 0
+ && SetLocalTime (&st) != 0;
+}
+
+int SystemStats::getPageSize()
+{
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo (&systemInfo);
+
+ return (int) systemInfo.dwPageSize;
+}
+
+//==============================================================================
+String SystemStats::getLogonName()
+{
+ TCHAR text [256] = { 0 };
+ DWORD len = (DWORD) numElementsInArray (text) - 1;
+ GetUserName (text, &len);
+ return String (text, len);
+}
+
+String SystemStats::getFullUserName()
+{
+ return getLogonName();
+}
+
+String SystemStats::getComputerName()
+{
+ TCHAR text [MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
+ DWORD len = (DWORD) numElementsInArray (text) - 1;
+ GetComputerName (text, &len);
+ return String (text, len);
+}
+
+static String getLocaleValue (LCID locale, LCTYPE key, const char* defaultValue)
+{
+ TCHAR buffer [256] = { 0 };
+ if (GetLocaleInfo (locale, key, buffer, 255) > 0)
+ return buffer;
+
+ return defaultValue;
+}
+
+String SystemStats::getUserLanguage() { return getLocaleValue (LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, "en"); }
+String SystemStats::getUserRegion() { return getLocaleValue (LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, "US"); }
+
+String SystemStats::getDisplayLanguage()
+{
+ DynamicLibrary dll ("kernel32.dll");
+ JUCE_LOAD_WINAPI_FUNCTION (dll, GetUserDefaultUILanguage, getUserDefaultUILanguage, LANGID, (void))
+
+ if (getUserDefaultUILanguage == nullptr)
+ return "en";
+
+ const DWORD langID = MAKELCID (getUserDefaultUILanguage(), SORT_DEFAULT);
+
+ String mainLang (getLocaleValue (langID, LOCALE_SISO639LANGNAME, "en"));
+ String region (getLocaleValue (langID, LOCALE_SISO3166CTRYNAME, nullptr));
+
+ if (region.isNotEmpty())
+ mainLang << '-' << region;
+
+ return mainLang;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Threads.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Threads.cpp
new file mode 100644
index 0000000..4eb24e2
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/native/juce_win32_Threads.cpp
@@ -0,0 +1,625 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+HWND juce_messageWindowHandle = 0; // (this is used by other parts of the codebase)
+
+void* getUser32Function (const char* functionName)
+{
+ HMODULE module = GetModuleHandleA ("user32.dll");
+ jassert (module != 0);
+ return (void*) GetProcAddress (module, functionName);
+}
+
+//==============================================================================
+#if ! JUCE_USE_INTRINSICS
+// In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in
+// older ones we have to actually call the ops as win32 functions..
+long juce_InterlockedExchange (volatile long* a, long b) noexcept { return InterlockedExchange (a, b); }
+long juce_InterlockedIncrement (volatile long* a) noexcept { return InterlockedIncrement (a); }
+long juce_InterlockedDecrement (volatile long* a) noexcept { return InterlockedDecrement (a); }
+long juce_InterlockedExchangeAdd (volatile long* a, long b) noexcept { return InterlockedExchangeAdd (a, b); }
+long juce_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept { return InterlockedCompareExchange (a, b, c); }
+
+__int64 juce_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) noexcept
+{
+ jassertfalse; // This operation isn't available in old MS compiler versions!
+
+ __int64 oldValue = *value;
+ if (oldValue == valueToCompare)
+ *value = newValue;
+
+ return oldValue;
+}
+
+#endif
+
+//==============================================================================
+CriticalSection::CriticalSection() noexcept
+{
+ // (just to check the MS haven't changed this structure and broken things...)
+ #if JUCE_VC7_OR_EARLIER
+ static_jassert (sizeof (CRITICAL_SECTION) <= 24);
+ #else
+ static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (lock));
+ #endif
+
+ InitializeCriticalSection ((CRITICAL_SECTION*) lock);
+}
+
+CriticalSection::~CriticalSection() noexcept { DeleteCriticalSection ((CRITICAL_SECTION*) lock); }
+void CriticalSection::enter() const noexcept { EnterCriticalSection ((CRITICAL_SECTION*) lock); }
+bool CriticalSection::tryEnter() const noexcept { return TryEnterCriticalSection ((CRITICAL_SECTION*) lock) != FALSE; }
+void CriticalSection::exit() const noexcept { LeaveCriticalSection ((CRITICAL_SECTION*) lock); }
+
+
+//==============================================================================
+WaitableEvent::WaitableEvent (const bool manualReset) noexcept
+ : handle (CreateEvent (0, manualReset ? TRUE : FALSE, FALSE, 0)) {}
+
+WaitableEvent::~WaitableEvent() noexcept { CloseHandle (handle); }
+
+void WaitableEvent::signal() const noexcept { SetEvent (handle); }
+void WaitableEvent::reset() const noexcept { ResetEvent (handle); }
+
+bool WaitableEvent::wait (const int timeOutMs) const noexcept
+{
+ return WaitForSingleObject (handle, (DWORD) timeOutMs) == WAIT_OBJECT_0;
+}
+
+//==============================================================================
+void JUCE_API juce_threadEntryPoint (void*);
+
+static unsigned int __stdcall threadEntryProc (void* userData)
+{
+ if (juce_messageWindowHandle != 0)
+ AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0),
+ GetCurrentThreadId(), TRUE);
+
+ juce_threadEntryPoint (userData);
+
+ _endthreadex (0);
+ return 0;
+}
+
+void Thread::launchThread()
+{
+ unsigned int newThreadId;
+ threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId);
+ threadId = (ThreadID) newThreadId;
+}
+
+void Thread::closeThreadHandle()
+{
+ CloseHandle ((HANDLE) threadHandle);
+ threadId = 0;
+ threadHandle = 0;
+}
+
+void Thread::killThread()
+{
+ if (threadHandle != 0)
+ {
+ #if JUCE_DEBUG
+ OutputDebugStringA ("** Warning - Forced thread termination **\n");
+ #endif
+ TerminateThread (threadHandle, 0);
+ }
+}
+
+void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)
+{
+ #if JUCE_DEBUG && JUCE_MSVC
+ struct
+ {
+ DWORD dwType;
+ LPCSTR szName;
+ DWORD dwThreadID;
+ DWORD dwFlags;
+ } info;
+
+ info.dwType = 0x1000;
+ info.szName = name.toUTF8();
+ info.dwThreadID = GetCurrentThreadId();
+ info.dwFlags = 0;
+
+ __try
+ {
+ RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {}
+ #else
+ (void) name;
+ #endif
+}
+
+Thread::ThreadID JUCE_CALLTYPE Thread::getCurrentThreadId()
+{
+ return (ThreadID) (pointer_sized_int) GetCurrentThreadId();
+}
+
+bool Thread::setThreadPriority (void* handle, int priority)
+{
+ int pri = THREAD_PRIORITY_TIME_CRITICAL;
+
+ if (priority < 1) pri = THREAD_PRIORITY_IDLE;
+ else if (priority < 2) pri = THREAD_PRIORITY_LOWEST;
+ else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL;
+ else if (priority < 7) pri = THREAD_PRIORITY_NORMAL;
+ else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL;
+ else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;
+
+ if (handle == 0)
+ handle = GetCurrentThread();
+
+ return SetThreadPriority (handle, pri) != FALSE;
+}
+
+void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
+{
+ SetThreadAffinityMask (GetCurrentThread(), affinityMask);
+}
+
+//==============================================================================
+struct SleepEvent
+{
+ SleepEvent() noexcept
+ : handle (CreateEvent (nullptr, FALSE, FALSE,
+ #if JUCE_DEBUG
+ _T("JUCE Sleep Event")))
+ #else
+ nullptr))
+ #endif
+ {}
+
+ ~SleepEvent() noexcept
+ {
+ CloseHandle (handle);
+ handle = 0;
+ }
+
+ HANDLE handle;
+};
+
+static SleepEvent sleepEvent;
+
+void JUCE_CALLTYPE Thread::sleep (const int millisecs)
+{
+ jassert (millisecs >= 0);
+
+ if (millisecs >= 10 || sleepEvent.handle == 0)
+ Sleep ((DWORD) millisecs);
+ else
+ // unlike Sleep() this is guaranteed to return to the current thread after
+ // the time expires, so we'll use this for short waits, which are more likely
+ // to need to be accurate
+ WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs);
+}
+
+void Thread::yield()
+{
+ Sleep (0);
+}
+
+//==============================================================================
+static int lastProcessPriority = -1;
+
+// called when the app gains focus because Windows does weird things to process priority
+// when you swap apps, and this forces an update when the app is brought to the front.
+void juce_repeatLastProcessPriority()
+{
+ if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..)
+ {
+ DWORD p;
+
+ switch (lastProcessPriority)
+ {
+ case Process::LowPriority: p = IDLE_PRIORITY_CLASS; break;
+ case Process::NormalPriority: p = NORMAL_PRIORITY_CLASS; break;
+ case Process::HighPriority: p = HIGH_PRIORITY_CLASS; break;
+ case Process::RealtimePriority: p = REALTIME_PRIORITY_CLASS; break;
+ default: jassertfalse; return; // bad priority value
+ }
+
+ SetPriorityClass (GetCurrentProcess(), p);
+ }
+}
+
+void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)
+{
+ if (lastProcessPriority != (int) prior)
+ {
+ lastProcessPriority = (int) prior;
+ juce_repeatLastProcessPriority();
+ }
+}
+
+JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger()
+{
+ return IsDebuggerPresent() != FALSE;
+}
+
+bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
+{
+ return juce_isRunningUnderDebugger();
+}
+
+static void* currentModuleHandle = nullptr;
+
+void* JUCE_CALLTYPE Process::getCurrentModuleInstanceHandle() noexcept
+{
+ if (currentModuleHandle == nullptr)
+ currentModuleHandle = GetModuleHandleA (nullptr);
+
+ return currentModuleHandle;
+}
+
+void JUCE_CALLTYPE Process::setCurrentModuleInstanceHandle (void* const newHandle) noexcept
+{
+ currentModuleHandle = newHandle;
+}
+
+void JUCE_CALLTYPE Process::raisePrivilege()
+{
+ jassertfalse; // xxx not implemented
+}
+
+void JUCE_CALLTYPE Process::lowerPrivilege()
+{
+ jassertfalse; // xxx not implemented
+}
+
+void JUCE_CALLTYPE Process::terminate()
+{
+ #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
+ _CrtDumpMemoryLeaks();
+ #endif
+
+ // bullet in the head in case there's a problem shutting down..
+ ExitProcess (1);
+}
+
+bool juce_isRunningInWine()
+{
+ HMODULE ntdll = GetModuleHandleA ("ntdll");
+ return ntdll != 0 && GetProcAddress (ntdll, "wine_get_version") != nullptr;
+}
+
+//==============================================================================
+bool DynamicLibrary::open (const String& name)
+{
+ close();
+
+ JUCE_TRY
+ {
+ handle = LoadLibrary (name.toWideCharPointer());
+ }
+ JUCE_CATCH_ALL
+
+ return handle != nullptr;
+}
+
+void DynamicLibrary::close()
+{
+ JUCE_TRY
+ {
+ if (handle != nullptr)
+ {
+ FreeLibrary ((HMODULE) handle);
+ handle = nullptr;
+ }
+ }
+ JUCE_CATCH_ALL
+}
+
+void* DynamicLibrary::getFunction (const String& functionName) noexcept
+{
+ return handle != nullptr ? (void*) GetProcAddress ((HMODULE) handle, functionName.toUTF8()) // (void* cast is required for mingw)
+ : nullptr;
+}
+
+
+//==============================================================================
+class InterProcessLock::Pimpl
+{
+public:
+ Pimpl (String name, const int timeOutMillisecs)
+ : handle (0), refCount (1)
+ {
+ name = name.replaceCharacter ('\\', '/');
+ handle = CreateMutexW (0, TRUE, ("Global\\" + name).toWideCharPointer());
+
+ // Not 100% sure why a global mutex sometimes can't be allocated, but if it fails, fall back to
+ // a local one. (A local one also sometimes fails on other machines so neither type appears to be
+ // universally reliable)
+ if (handle == 0)
+ handle = CreateMutexW (0, TRUE, ("Local\\" + name).toWideCharPointer());
+
+ if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ if (timeOutMillisecs == 0)
+ {
+ close();
+ return;
+ }
+
+ switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ break;
+
+ case WAIT_TIMEOUT:
+ default:
+ close();
+ break;
+ }
+ }
+ }
+
+ ~Pimpl()
+ {
+ close();
+ }
+
+ void close()
+ {
+ if (handle != 0)
+ {
+ ReleaseMutex (handle);
+ CloseHandle (handle);
+ handle = 0;
+ }
+ }
+
+ HANDLE handle;
+ int refCount;
+};
+
+InterProcessLock::InterProcessLock (const String& name_)
+ : name (name_)
+{
+}
+
+InterProcessLock::~InterProcessLock()
+{
+}
+
+bool InterProcessLock::enter (const int timeOutMillisecs)
+{
+ const ScopedLock sl (lock);
+
+ if (pimpl == nullptr)
+ {
+ pimpl = new Pimpl (name, timeOutMillisecs);
+
+ if (pimpl->handle == 0)
+ pimpl = nullptr;
+ }
+ else
+ {
+ pimpl->refCount++;
+ }
+
+ return pimpl != nullptr;
+}
+
+void InterProcessLock::exit()
+{
+ const ScopedLock sl (lock);
+
+ // Trying to release the lock too many times!
+ jassert (pimpl != nullptr);
+
+ if (pimpl != nullptr && --(pimpl->refCount) == 0)
+ pimpl = nullptr;
+}
+
+//==============================================================================
+class ChildProcess::ActiveProcess
+{
+public:
+ ActiveProcess (const String& command, int streamFlags)
+ : ok (false), readPipe (0), writePipe (0)
+ {
+ SECURITY_ATTRIBUTES securityAtts = { 0 };
+ securityAtts.nLength = sizeof (securityAtts);
+ securityAtts.bInheritHandle = TRUE;
+
+ if (CreatePipe (&readPipe, &writePipe, &securityAtts, 0)
+ && SetHandleInformation (readPipe, HANDLE_FLAG_INHERIT, 0))
+ {
+ STARTUPINFOW startupInfo = { 0 };
+ startupInfo.cb = sizeof (startupInfo);
+
+ startupInfo.hStdOutput = (streamFlags | wantStdOut) != 0 ? writePipe : 0;
+ startupInfo.hStdError = (streamFlags | wantStdErr) != 0 ? writePipe : 0;
+ startupInfo.dwFlags = STARTF_USESTDHANDLES;
+
+ ok = CreateProcess (nullptr, const_cast <LPWSTR> (command.toWideCharPointer()),
+ nullptr, nullptr, TRUE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
+ nullptr, nullptr, &startupInfo, &processInfo) != FALSE;
+ }
+ }
+
+ ~ActiveProcess()
+ {
+ if (ok)
+ {
+ CloseHandle (processInfo.hThread);
+ CloseHandle (processInfo.hProcess);
+ }
+
+ if (readPipe != 0)
+ CloseHandle (readPipe);
+
+ if (writePipe != 0)
+ CloseHandle (writePipe);
+ }
+
+ bool isRunning() const noexcept
+ {
+ return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0;
+ }
+
+ int read (void* dest, int numNeeded) const noexcept
+ {
+ int total = 0;
+
+ while (ok && numNeeded > 0)
+ {
+ DWORD available = 0;
+
+ if (! PeekNamedPipe ((HANDLE) readPipe, nullptr, 0, nullptr, &available, nullptr))
+ break;
+
+ const int numToDo = jmin ((int) available, numNeeded);
+
+ if (available == 0)
+ {
+ if (! isRunning())
+ break;
+
+ Thread::yield();
+ }
+ else
+ {
+ DWORD numRead = 0;
+ if (! ReadFile ((HANDLE) readPipe, dest, numToDo, &numRead, nullptr))
+ break;
+
+ total += numRead;
+ dest = addBytesToPointer (dest, numRead);
+ numNeeded -= numRead;
+ }
+ }
+
+ return total;
+ }
+
+ bool killProcess() const noexcept
+ {
+ return TerminateProcess (processInfo.hProcess, 0) != FALSE;
+ }
+
+ uint32 getExitCode() const noexcept
+ {
+ DWORD exitCode = 0;
+ GetExitCodeProcess (processInfo.hProcess, &exitCode);
+ return (uint32) exitCode;
+ }
+
+ bool ok;
+
+private:
+ HANDLE readPipe, writePipe;
+ PROCESS_INFORMATION processInfo;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess)
+};
+
+bool ChildProcess::start (const String& command, int streamFlags)
+{
+ activeProcess = new ActiveProcess (command, streamFlags);
+
+ if (! activeProcess->ok)
+ activeProcess = nullptr;
+
+ return activeProcess != nullptr;
+}
+
+bool ChildProcess::start (const StringArray& args, int streamFlags)
+{
+ String escaped;
+
+ for (int i = 0; i < args.size(); ++i)
+ {
+ String arg (args[i]);
+
+ // If there are spaces, surround it with quotes. If there are quotes,
+ // replace them with \" so that CommandLineToArgv will correctly parse them.
+ if (arg.containsAnyOf ("\" "))
+ arg = arg.replace ("\"", "\\\"").quoted();
+
+ escaped << arg << ' ';
+ }
+
+ return start (escaped.trim(), streamFlags);
+}
+
+//==============================================================================
+struct HighResolutionTimer::Pimpl
+{
+ Pimpl (HighResolutionTimer& t) noexcept : owner (t), periodMs (0)
+ {
+ }
+
+ ~Pimpl()
+ {
+ jassert (periodMs == 0);
+ }
+
+ void start (int newPeriod)
+ {
+ if (newPeriod != periodMs)
+ {
+ stop();
+ periodMs = newPeriod;
+
+ TIMECAPS tc;
+ if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR)
+ {
+ const int actualPeriod = jlimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod);
+
+ timerID = timeSetEvent (actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this,
+ TIME_PERIODIC | TIME_CALLBACK_FUNCTION | 0x100 /*TIME_KILL_SYNCHRONOUS*/);
+ }
+ }
+ }
+
+ void stop()
+ {
+ periodMs = 0;
+ timeKillEvent (timerID);
+ }
+
+ HighResolutionTimer& owner;
+ int periodMs;
+
+private:
+ unsigned int timerID;
+
+ static void __stdcall callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR)
+ {
+ if (Pimpl* const timer = reinterpret_cast<Pimpl*> (userInfo))
+ if (timer->periodMs != 0)
+ timer->owner.hiResTimerCallback();
+ }
+
+ JUCE_DECLARE_NON_COPYABLE (Pimpl)
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.cpp
new file mode 100644
index 0000000..6c4d087
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.cpp
@@ -0,0 +1,149 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+IPAddress::IPAddress() noexcept
+{
+ address[0] = 0; address[1] = 0;
+ address[2] = 0; address[3] = 0;
+}
+
+IPAddress::IPAddress (const uint8 bytes[4]) noexcept
+{
+ address[0] = bytes[0]; address[1] = bytes[1];
+ address[2] = bytes[2]; address[3] = bytes[3];
+}
+
+IPAddress::IPAddress (uint8 a0, uint8 a1, uint8 a2, uint8 a3) noexcept
+{
+ address[0] = a0; address[1] = a1;
+ address[2] = a2; address[3] = a3;
+}
+
+IPAddress::IPAddress (uint32 n) noexcept
+{
+ address[0] = (n >> 24);
+ address[1] = (n >> 16) & 255;
+ address[2] = (n >> 8) & 255;
+ address[3] = (n & 255);
+}
+
+IPAddress::IPAddress (const String& adr)
+{
+ StringArray tokens;
+ tokens.addTokens (adr, ".", String());
+
+ for (int i = 0; i < 4; ++i)
+ address[i] = (uint8) tokens[i].getIntValue();
+}
+
+String IPAddress::toString() const
+{
+ String s ((int) address[0]);
+
+ for (int i = 1; i < 4; ++i)
+ s << '.' << (int) address[i];
+
+ return s;
+}
+
+IPAddress IPAddress::any() noexcept { return IPAddress(); }
+IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); }
+IPAddress IPAddress::local() noexcept { return IPAddress (127, 0, 0, 1); }
+
+bool IPAddress::operator== (const IPAddress& other) const noexcept
+{
+ return address[0] == other.address[0]
+ && address[1] == other.address[1]
+ && address[2] == other.address[2]
+ && address[3] == other.address[3];
+}
+
+bool IPAddress::operator!= (const IPAddress& other) const noexcept
+{
+ return ! operator== (other);
+}
+
+#if ! JUCE_WINDOWS
+static void addAddress (const sockaddr_in* addr_in, Array<IPAddress>& result)
+{
+ in_addr_t addr = addr_in->sin_addr.s_addr;
+
+ if (addr != INADDR_NONE)
+ result.addIfNotAlreadyThere (IPAddress (ntohl (addr)));
+}
+
+static void findIPAddresses (int sock, Array<IPAddress>& result)
+{
+ ifconf cfg;
+ HeapBlock<char> buffer;
+ int bufferSize = 1024;
+
+ do
+ {
+ bufferSize *= 2;
+ buffer.calloc ((size_t) bufferSize);
+
+ cfg.ifc_len = bufferSize;
+ cfg.ifc_buf = buffer;
+
+ if (ioctl (sock, SIOCGIFCONF, &cfg) < 0 && errno != EINVAL)
+ return;
+
+ } while (bufferSize < cfg.ifc_len + 2 * (int) (IFNAMSIZ + sizeof (struct sockaddr_in6)));
+
+ #if JUCE_MAC || JUCE_IOS
+ while (cfg.ifc_len >= (int) (IFNAMSIZ + sizeof (struct sockaddr_in)))
+ {
+ if (cfg.ifc_req->ifr_addr.sa_family == AF_INET) // Skip non-internet addresses
+ addAddress ((const sockaddr_in*) &cfg.ifc_req->ifr_addr, result);
+
+ cfg.ifc_len -= IFNAMSIZ + cfg.ifc_req->ifr_addr.sa_len;
+ cfg.ifc_buf += IFNAMSIZ + cfg.ifc_req->ifr_addr.sa_len;
+ }
+ #else
+ for (size_t i = 0; i < cfg.ifc_len / sizeof (struct ifreq); ++i)
+ {
+ const ifreq& item = cfg.ifc_req[i];
+
+ if (item.ifr_addr.sa_family == AF_INET)
+ addAddress ((const sockaddr_in*) &item.ifr_addr, result);
+ }
+ #endif
+}
+
+void IPAddress::findAllAddresses (Array<IPAddress>& result)
+{
+ const int sock = socket (AF_INET, SOCK_DGRAM, 0); // a dummy socket to execute the IO control
+
+ if (sock >= 0)
+ {
+ findIPAddresses (sock, result);
+ ::close (sock);
+ }
+}
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.h b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.h
new file mode 100644
index 0000000..1f2f0e8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_IPAddress.h
@@ -0,0 +1,82 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_IPADDRESS_H_INCLUDED
+#define JUCE_IPADDRESS_H_INCLUDED
+
+
+//==============================================================================
+/**
+ An IPV4 address.
+*/
+class JUCE_API IPAddress
+{
+public:
+ //==============================================================================
+ /** Populates a list of all the IP addresses that this machine is using. */
+ static void findAllAddresses (Array<IPAddress>& results);
+
+ //==============================================================================
+ /** Creates a null address (0.0.0.0). */
+ IPAddress() noexcept;
+
+ /** Creates an address from 4 bytes. */
+ explicit IPAddress (const uint8 bytes[4]) noexcept;
+
+ /** Creates an address from 4 bytes. */
+ IPAddress (uint8 address1, uint8 address2, uint8 address3, uint8 address4) noexcept;
+
+ /** Creates an address from a packed 32-bit integer, where the MSB is
+ the first number in the address, and the LSB is the last.
+ */
+ explicit IPAddress (uint32 asNativeEndian32Bit) noexcept;
+
+ /** Parses a string IP address of the form "a.b.c.d". */
+ explicit IPAddress (const String& address);
+
+ /** Returns a dot-separated string in the form "1.2.3.4" */
+ String toString() const;
+
+ /** Returns an address meaning "any" (0.0.0.0) */
+ static IPAddress any() noexcept;
+
+ /** Returns an address meaning "broadcast" (255.255.255.255) */
+ static IPAddress broadcast() noexcept;
+
+ /** Returns an address meaning "localhost" (127.0.0.1) */
+ static IPAddress local() noexcept;
+
+ bool operator== (const IPAddress& other) const noexcept;
+ bool operator!= (const IPAddress& other) const noexcept;
+
+ /** The elements of the IP address. */
+ uint8 address[4];
+};
+
+
+#endif // JUCE_IPADDRESS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.cpp
new file mode 100644
index 0000000..b7cb3c1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.cpp
@@ -0,0 +1,78 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+MACAddress::MACAddress()
+{
+ zeromem (address, sizeof (address));
+}
+
+MACAddress::MACAddress (const MACAddress& other)
+{
+ memcpy (address, other.address, sizeof (address));
+}
+
+MACAddress& MACAddress::operator= (const MACAddress& other)
+{
+ memcpy (address, other.address, sizeof (address));
+ return *this;
+}
+
+MACAddress::MACAddress (const uint8 bytes[6])
+{
+ memcpy (address, bytes, sizeof (address));
+}
+
+String MACAddress::toString() const
+{
+ String s;
+
+ for (size_t i = 0; i < sizeof (address); ++i)
+ {
+ s << String::toHexString ((int) address[i]).paddedLeft ('0', 2);
+
+ if (i < sizeof (address) - 1)
+ s << '-';
+ }
+
+ return s;
+}
+
+int64 MACAddress::toInt64() const noexcept
+{
+ int64 n = 0;
+
+ for (int i = (int) sizeof (address); --i >= 0;)
+ n = (n << 8) | address[i];
+
+ return n;
+}
+
+bool MACAddress::isNull() const noexcept { return toInt64() == 0; }
+
+bool MACAddress::operator== (const MACAddress& other) const noexcept { return memcmp (address, other.address, sizeof (address)) == 0; }
+bool MACAddress::operator!= (const MACAddress& other) const noexcept { return ! operator== (other); }
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.h b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.h
new file mode 100644
index 0000000..67e119e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_MACAddress.h
@@ -0,0 +1,82 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MACADDRESS_H_INCLUDED
+#define JUCE_MACADDRESS_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a MAC network card adapter address ID.
+*/
+class JUCE_API MACAddress
+{
+public:
+ //==============================================================================
+ /** Populates a list of the MAC addresses of all the available network cards. */
+ static void findAllAddresses (Array<MACAddress>& results);
+
+ //==============================================================================
+ /** Creates a null address (00-00-00-00-00-00). */
+ MACAddress();
+
+ /** Creates a copy of another address. */
+ MACAddress (const MACAddress&);
+
+ /** Creates a copy of another address. */
+ MACAddress& operator= (const MACAddress&);
+
+ /** Creates an address from 6 bytes. */
+ explicit MACAddress (const uint8 bytes[6]);
+
+ /** Returns a pointer to the 6 bytes that make up this address. */
+ const uint8* getBytes() const noexcept { return address; }
+
+ /** Returns a dash-separated string in the form "11-22-33-44-55-66" */
+ String toString() const;
+
+ /** Returns the address in the lower 6 bytes of an int64.
+
+ This uses a little-endian arrangement, with the first byte of the address being
+ stored in the least-significant byte of the result value.
+ */
+ int64 toInt64() const noexcept;
+
+ /** Returns true if this address is null (00-00-00-00-00-00). */
+ bool isNull() const noexcept;
+
+ bool operator== (const MACAddress&) const noexcept;
+ bool operator!= (const MACAddress&) const noexcept;
+
+ //==============================================================================
+private:
+ uint8 address[6];
+};
+
+
+#endif // JUCE_MACADDRESS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.cpp
new file mode 100644
index 0000000..488e63f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.cpp
@@ -0,0 +1,66 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+NamedPipe::NamedPipe()
+{
+}
+
+NamedPipe::~NamedPipe()
+{
+ close();
+}
+
+bool NamedPipe::openExisting (const String& pipeName)
+{
+ close();
+
+ ScopedWriteLock sl (lock);
+ currentPipeName = pipeName;
+ return openInternal (pipeName, false);
+}
+
+bool NamedPipe::isOpen() const
+{
+ return pimpl != nullptr;
+}
+
+bool NamedPipe::createNewPipe (const String& pipeName)
+{
+ close();
+
+ ScopedWriteLock sl (lock);
+ currentPipeName = pipeName;
+ return openInternal (pipeName, true);
+}
+
+String NamedPipe::getName() const
+{
+ return currentPipeName;
+}
+
+// other methods for this class are implemented in the platform-specific files
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.h b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.h
new file mode 100644
index 0000000..d2029bd
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_NamedPipe.h
@@ -0,0 +1,104 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_NAMEDPIPE_H_INCLUDED
+#define JUCE_NAMEDPIPE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A cross-process pipe that can have data written to and read from it.
+
+ Two processes can use NamedPipe objects to exchange blocks of data.
+
+ @see InterprocessConnection
+*/
+class JUCE_API NamedPipe
+{
+public:
+ //==============================================================================
+ /** Creates a NamedPipe. */
+ NamedPipe();
+
+ /** Destructor. */
+ ~NamedPipe();
+
+ //==============================================================================
+ /** Tries to open a pipe that already exists.
+ Returns true if it succeeds.
+ */
+ bool openExisting (const String& pipeName);
+
+ /** Tries to create a new pipe.
+ Returns true if it succeeds.
+ */
+ bool createNewPipe (const String& pipeName);
+
+ /** Closes the pipe, if it's open. */
+ void close();
+
+ /** True if the pipe is currently open. */
+ bool isOpen() const;
+
+ /** Returns the last name that was used to try to open this pipe. */
+ String getName() const;
+
+ //==============================================================================
+ /** Reads data from the pipe.
+
+ This will block until another thread has written enough data into the pipe to fill
+ the number of bytes specified, or until another thread calls the cancelPendingReads()
+ method.
+
+ If the operation fails, it returns -1, otherwise, it will return the number of
+ bytes read.
+
+ If timeOutMilliseconds is less than zero, it will wait indefinitely, otherwise
+ this is a maximum timeout for reading from the pipe.
+ */
+ int read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds);
+
+ /** Writes some data to the pipe.
+ @returns the number of bytes written, or -1 on failure.
+ */
+ int write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds);
+
+private:
+ //==============================================================================
+ JUCE_PUBLIC_IN_DLL_BUILD (class Pimpl)
+ ScopedPointer<Pimpl> pimpl;
+ String currentPipeName;
+ ReadWriteLock lock;
+
+ bool openInternal (const String& pipeName, const bool createPipe);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NamedPipe)
+};
+
+
+#endif // JUCE_NAMEDPIPE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.cpp
new file mode 100644
index 0000000..97d0e0f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.cpp
@@ -0,0 +1,593 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable : 4127 4389 4018)
+#endif
+
+#ifndef AI_NUMERICSERV // (missing in older Mac SDKs)
+ #define AI_NUMERICSERV 0x1000
+#endif
+
+#if JUCE_WINDOWS
+ typedef int juce_socklen_t;
+ typedef SOCKET SocketHandle;
+#else
+ typedef socklen_t juce_socklen_t;
+ typedef int SocketHandle;
+#endif
+
+//==============================================================================
+namespace SocketHelpers
+{
+ static void initSockets()
+ {
+ #if JUCE_WINDOWS
+ static bool socketsStarted = false;
+
+ if (! socketsStarted)
+ {
+ socketsStarted = true;
+
+ WSADATA wsaData;
+ const WORD wVersionRequested = MAKEWORD (1, 1);
+ WSAStartup (wVersionRequested, &wsaData);
+ }
+ #endif
+ }
+
+ static bool resetSocketOptions (const SocketHandle handle, const bool isDatagram, const bool allowBroadcast) noexcept
+ {
+ const int sndBufSize = 65536;
+ const int rcvBufSize = 65536;
+ const int one = 1;
+
+ return handle > 0
+ && setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0
+ && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0
+ && (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0)
+ : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0));
+ }
+
+ static bool bindSocketToPort (const SocketHandle handle, const int port) noexcept
+ {
+ if (handle <= 0 || port <= 0)
+ return false;
+
+ struct sockaddr_in servTmpAddr;
+ zerostruct (servTmpAddr); // (can't use "= { 0 }" on this object because it's typedef'ed as a C struct)
+ servTmpAddr.sin_family = PF_INET;
+ servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY);
+ servTmpAddr.sin_port = htons ((uint16) port);
+
+ return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0;
+ }
+
+ static int readSocket (const SocketHandle handle,
+ void* const destBuffer, const int maxBytesToRead,
+ bool volatile& connected,
+ const bool blockUntilSpecifiedAmountHasArrived) noexcept
+ {
+ int bytesRead = 0;
+
+ while (bytesRead < maxBytesToRead)
+ {
+ int bytesThisTime;
+
+ #if JUCE_WINDOWS
+ bytesThisTime = recv (handle, static_cast<char*> (destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0);
+ #else
+ while ((bytesThisTime = (int) ::read (handle, addBytesToPointer (destBuffer, bytesRead),
+ (size_t) (maxBytesToRead - bytesRead))) < 0
+ && errno == EINTR
+ && connected)
+ {
+ }
+ #endif
+
+ if (bytesThisTime <= 0 || ! connected)
+ {
+ if (bytesRead == 0)
+ bytesRead = -1;
+
+ break;
+ }
+
+ bytesRead += bytesThisTime;
+
+ if (! blockUntilSpecifiedAmountHasArrived)
+ break;
+ }
+
+ return bytesRead;
+ }
+
+ static int waitForReadiness (const SocketHandle handle, const bool forReading, const int timeoutMsecs) noexcept
+ {
+ struct timeval timeout;
+ struct timeval* timeoutp;
+
+ if (timeoutMsecs >= 0)
+ {
+ timeout.tv_sec = timeoutMsecs / 1000;
+ timeout.tv_usec = (timeoutMsecs % 1000) * 1000;
+ timeoutp = &timeout;
+ }
+ else
+ {
+ timeoutp = 0;
+ }
+
+ fd_set rset, wset;
+ FD_ZERO (&rset);
+ FD_SET (handle, &rset);
+ FD_ZERO (&wset);
+ FD_SET (handle, &wset);
+
+ fd_set* const prset = forReading ? &rset : nullptr;
+ fd_set* const pwset = forReading ? nullptr : &wset;
+
+ #if JUCE_WINDOWS
+ if (select ((int) handle + 1, prset, pwset, 0, timeoutp) < 0)
+ return -1;
+ #else
+ {
+ int result;
+ while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0
+ && errno == EINTR)
+ {
+ }
+
+ if (result < 0)
+ return -1;
+ }
+ #endif
+
+ {
+ int opt;
+ juce_socklen_t len = sizeof (opt);
+
+ if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0
+ || opt != 0)
+ return -1;
+ }
+
+ return FD_ISSET (handle, forReading ? &rset : &wset) ? 1 : 0;
+ }
+
+ static bool setSocketBlockingState (const SocketHandle handle, const bool shouldBlock) noexcept
+ {
+ #if JUCE_WINDOWS
+ u_long nonBlocking = shouldBlock ? 0 : (u_long) 1;
+ return ioctlsocket (handle, FIONBIO, &nonBlocking) == 0;
+ #else
+ int socketFlags = fcntl (handle, F_GETFL, 0);
+
+ if (socketFlags == -1)
+ return false;
+
+ if (shouldBlock)
+ socketFlags &= ~O_NONBLOCK;
+ else
+ socketFlags |= O_NONBLOCK;
+
+ return fcntl (handle, F_SETFL, socketFlags) == 0;
+ #endif
+ }
+
+ static bool connectSocket (int volatile& handle,
+ const bool isDatagram,
+ struct addrinfo** const serverAddress,
+ const String& hostName,
+ const int portNumber,
+ const int timeOutMillisecs) noexcept
+ {
+ struct addrinfo hints;
+ zerostruct (hints);
+
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = isDatagram ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ struct addrinfo* info = nullptr;
+ if (getaddrinfo (hostName.toUTF8(), String (portNumber).toUTF8(), &hints, &info) != 0
+ || info == nullptr)
+ return false;
+
+ if (handle < 0)
+ handle = (int) socket (info->ai_family, info->ai_socktype, 0);
+
+ if (handle < 0)
+ {
+ freeaddrinfo (info);
+ return false;
+ }
+
+ if (isDatagram)
+ {
+ if (*serverAddress != nullptr)
+ freeaddrinfo (*serverAddress);
+
+ *serverAddress = info;
+ return true;
+ }
+
+ setSocketBlockingState (handle, false);
+ const int result = ::connect (handle, info->ai_addr, (socklen_t) info->ai_addrlen);
+ freeaddrinfo (info);
+
+ if (result < 0)
+ {
+ #if JUCE_WINDOWS
+ if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+ #else
+ if (errno == EINPROGRESS)
+ #endif
+ {
+ if (waitForReadiness (handle, false, timeOutMillisecs) != 1)
+ {
+ setSocketBlockingState (handle, true);
+ return false;
+ }
+ }
+ }
+
+ setSocketBlockingState (handle, true);
+ resetSocketOptions (handle, false, false);
+
+ return true;
+ }
+}
+
+//==============================================================================
+StreamingSocket::StreamingSocket()
+ : portNumber (0),
+ handle (-1),
+ connected (false),
+ isListener (false)
+{
+ SocketHelpers::initSockets();
+}
+
+StreamingSocket::StreamingSocket (const String& host, int portNum, int h)
+ : hostName (host),
+ portNumber (portNum),
+ handle (h),
+ connected (true),
+ isListener (false)
+{
+ SocketHelpers::initSockets();
+ SocketHelpers::resetSocketOptions (h, false, false);
+}
+
+StreamingSocket::~StreamingSocket()
+{
+ close();
+}
+
+//==============================================================================
+int StreamingSocket::read (void* destBuffer, const int maxBytesToRead,
+ const bool blockUntilSpecifiedAmountHasArrived)
+{
+ return (connected && ! isListener) ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead,
+ connected, blockUntilSpecifiedAmountHasArrived)
+ : -1;
+}
+
+int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite)
+{
+ if (isListener || ! connected)
+ return -1;
+
+ #if JUCE_WINDOWS
+ return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0);
+ #else
+ int result;
+
+ while ((result = (int) ::write (handle, sourceBuffer, (size_t) numBytesToWrite)) < 0
+ && errno == EINTR)
+ {
+ }
+
+ return result;
+ #endif
+}
+
+//==============================================================================
+int StreamingSocket::waitUntilReady (const bool readyForReading,
+ const int timeoutMsecs) const
+{
+ return connected ? SocketHelpers::waitForReadiness (handle, readyForReading, timeoutMsecs)
+ : -1;
+}
+
+//==============================================================================
+bool StreamingSocket::bindToPort (const int port)
+{
+ return SocketHelpers::bindSocketToPort (handle, port);
+}
+
+bool StreamingSocket::connect (const String& remoteHostName,
+ const int remotePortNumber,
+ const int timeOutMillisecs)
+{
+ if (isListener)
+ {
+ jassertfalse; // a listener socket can't connect to another one!
+ return false;
+ }
+
+ if (connected)
+ close();
+
+ hostName = remoteHostName;
+ portNumber = remotePortNumber;
+ isListener = false;
+
+ connected = SocketHelpers::connectSocket (handle, false, nullptr, remoteHostName,
+ remotePortNumber, timeOutMillisecs);
+
+ if (! (connected && SocketHelpers::resetSocketOptions (handle, false, false)))
+ {
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+void StreamingSocket::close()
+{
+ #if JUCE_WINDOWS
+ if (handle != SOCKET_ERROR || connected)
+ closesocket (handle);
+
+ connected = false;
+ #else
+ if (connected)
+ {
+ connected = false;
+
+ if (isListener)
+ {
+ // need to do this to interrupt the accept() function..
+ StreamingSocket temp;
+ temp.connect (IPAddress::local().toString(), portNumber, 1000);
+ }
+ }
+
+ if (handle != -1)
+ ::close (handle);
+ #endif
+
+ hostName.clear();
+ portNumber = 0;
+ handle = -1;
+ isListener = false;
+}
+
+//==============================================================================
+bool StreamingSocket::createListener (const int newPortNumber, const String& localHostName)
+{
+ if (connected)
+ close();
+
+ hostName = "listener";
+ portNumber = newPortNumber;
+ isListener = true;
+
+ struct sockaddr_in servTmpAddr;
+ zerostruct (servTmpAddr);
+
+ servTmpAddr.sin_family = PF_INET;
+ servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ if (localHostName.isNotEmpty())
+ servTmpAddr.sin_addr.s_addr = ::inet_addr (localHostName.toUTF8());
+
+ servTmpAddr.sin_port = htons ((uint16) portNumber);
+
+ handle = (int) socket (AF_INET, SOCK_STREAM, 0);
+
+ if (handle < 0)
+ return false;
+
+ const int reuse = 1;
+ setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse));
+
+ if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0
+ || listen (handle, SOMAXCONN) < 0)
+ {
+ close();
+ return false;
+ }
+
+ connected = true;
+ return true;
+}
+
+StreamingSocket* StreamingSocket::waitForNextConnection() const
+{
+ // To call this method, you first have to use createListener() to
+ // prepare this socket as a listener.
+ jassert (isListener || ! connected);
+
+ if (connected && isListener)
+ {
+ struct sockaddr_storage address;
+ juce_socklen_t len = sizeof (address);
+ const int newSocket = (int) accept (handle, (struct sockaddr*) &address, &len);
+
+ if (newSocket >= 0 && connected)
+ return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
+ portNumber, newSocket);
+ }
+
+ return nullptr;
+}
+
+bool StreamingSocket::isLocal() const noexcept
+{
+ return hostName == "127.0.0.1";
+}
+
+
+//==============================================================================
+//==============================================================================
+DatagramSocket::DatagramSocket (const int localPortNumber, const bool canBroadcast)
+ : portNumber (0),
+ handle (-1),
+ connected (true),
+ allowBroadcast (canBroadcast),
+ serverAddress (nullptr)
+{
+ SocketHelpers::initSockets();
+
+ handle = (int) socket (AF_INET, SOCK_DGRAM, 0);
+ bindToPort (localPortNumber);
+}
+
+DatagramSocket::DatagramSocket (const String& host, const int portNum,
+ const int h, const int localPortNumber)
+ : hostName (host),
+ portNumber (portNum),
+ handle (h),
+ connected (true),
+ allowBroadcast (false),
+ serverAddress (nullptr)
+{
+ SocketHelpers::initSockets();
+
+ SocketHelpers::resetSocketOptions (h, true, allowBroadcast);
+ bindToPort (localPortNumber);
+}
+
+DatagramSocket::~DatagramSocket()
+{
+ close();
+
+ if (serverAddress != nullptr)
+ freeaddrinfo (static_cast <struct addrinfo*> (serverAddress));
+}
+
+void DatagramSocket::close()
+{
+ #if JUCE_WINDOWS
+ closesocket (handle);
+ connected = false;
+ #else
+ connected = false;
+ ::close (handle);
+ #endif
+
+ hostName.clear();
+ portNumber = 0;
+ handle = -1;
+}
+
+bool DatagramSocket::bindToPort (const int port)
+{
+ return SocketHelpers::bindSocketToPort (handle, port);
+}
+
+bool DatagramSocket::connect (const String& remoteHostName,
+ const int remotePortNumber,
+ const int timeOutMillisecs)
+{
+ if (connected)
+ close();
+
+ hostName = remoteHostName;
+ portNumber = remotePortNumber;
+
+ connected = SocketHelpers::connectSocket (handle, true, (struct addrinfo**) &serverAddress,
+ remoteHostName, remotePortNumber,
+ timeOutMillisecs);
+
+ if (! (connected && SocketHelpers::resetSocketOptions (handle, true, allowBroadcast)))
+ {
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+DatagramSocket* DatagramSocket::waitForNextConnection() const
+{
+ while (waitUntilReady (true, -1) == 1)
+ {
+ struct sockaddr_storage address;
+ juce_socklen_t len = sizeof (address);
+ char buf[1];
+
+ if (recvfrom (handle, buf, 0, 0, (struct sockaddr*) &address, &len) > 0)
+ return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
+ ntohs (((struct sockaddr_in*) &address)->sin_port),
+ -1, -1);
+ }
+
+ return nullptr;
+}
+
+//==============================================================================
+int DatagramSocket::waitUntilReady (const bool readyForReading,
+ const int timeoutMsecs) const
+{
+ return connected ? SocketHelpers::waitForReadiness (handle, readyForReading, timeoutMsecs)
+ : -1;
+}
+
+int DatagramSocket::read (void* destBuffer, const int maxBytesToRead, const bool blockUntilSpecifiedAmountHasArrived)
+{
+ return connected ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead,
+ connected, blockUntilSpecifiedAmountHasArrived)
+ : -1;
+}
+
+int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite)
+{
+ // You need to call connect() first to set the server address..
+ jassert (serverAddress != nullptr && connected);
+
+ return connected ? (int) sendto (handle, (const char*) sourceBuffer,
+ (size_t) numBytesToWrite, 0,
+ static_cast <const struct addrinfo*> (serverAddress)->ai_addr,
+ (juce_socklen_t) static_cast <const struct addrinfo*> (serverAddress)->ai_addrlen)
+ : -1;
+}
+
+bool DatagramSocket::isLocal() const noexcept
+{
+ return hostName == "127.0.0.1";
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.h b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.h
new file mode 100644
index 0000000..73795c9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_Socket.h
@@ -0,0 +1,305 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SOCKET_H_INCLUDED
+#define JUCE_SOCKET_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A wrapper for a streaming (TCP) socket.
+
+ This allows low-level use of sockets; for an easier-to-use messaging layer on top of
+ sockets, you could also try the InterprocessConnection class.
+
+ @see DatagramSocket, InterprocessConnection, InterprocessConnectionServer
+*/
+class JUCE_API StreamingSocket
+{
+public:
+ //==============================================================================
+ /** Creates an uninitialised socket.
+
+ To connect it, use the connect() method, after which you can read() or write()
+ to it.
+
+ To wait for other sockets to connect to this one, the createListener() method
+ enters "listener" mode, and can be used to spawn new sockets for each connection
+ that comes along.
+ */
+ StreamingSocket();
+
+ /** Destructor. */
+ ~StreamingSocket();
+
+ //==============================================================================
+ /** Binds the socket to the specified local port.
+
+ @returns true on success; false may indicate that another socket is already bound
+ on the same port
+ */
+ bool bindToPort (int localPortNumber);
+
+ /** Tries to connect the socket to hostname:port.
+
+ If timeOutMillisecs is 0, then this method will block until the operating system
+ rejects the connection (which could take a long time).
+
+ @returns true if it succeeds.
+ @see isConnected
+ */
+ bool connect (const String& remoteHostname,
+ int remotePortNumber,
+ int timeOutMillisecs = 3000);
+
+ /** True if the socket is currently connected. */
+ bool isConnected() const noexcept { return connected; }
+
+ /** Closes the connection. */
+ void close();
+
+ /** Returns the name of the currently connected host. */
+ const String& getHostName() const noexcept { return hostName; }
+
+ /** Returns the port number that's currently open. */
+ int getPort() const noexcept { return portNumber; }
+
+ /** True if the socket is connected to this machine rather than over the network. */
+ bool isLocal() const noexcept;
+
+ /** Returns the OS's socket handle that's currently open. */
+ int getRawSocketHandle() const noexcept { return handle; }
+
+ //==============================================================================
+ /** Waits until the socket is ready for reading or writing.
+
+ If readyForReading is true, it will wait until the socket is ready for
+ reading; if false, it will wait until it's ready for writing.
+
+ If the timeout is < 0, it will wait forever, or else will give up after
+ the specified time.
+
+ If the socket is ready on return, this returns 1. If it times-out before
+ the socket becomes ready, it returns 0. If an error occurs, it returns -1.
+ */
+ int waitUntilReady (bool readyForReading,
+ int timeoutMsecs) const;
+
+ /** Reads bytes from the socket.
+
+ If blockUntilSpecifiedAmountHasArrived is true, the method will block until
+ maxBytesToRead bytes have been read, (or until an error occurs). If this
+ flag is false, the method will return as much data as is currently available
+ without blocking.
+
+ @returns the number of bytes read, or -1 if there was an error.
+ @see waitUntilReady
+ */
+ int read (void* destBuffer, int maxBytesToRead,
+ bool blockUntilSpecifiedAmountHasArrived);
+
+ /** Writes bytes to the socket from a buffer.
+
+ Note that this method will block unless you have checked the socket is ready
+ for writing before calling it (see the waitUntilReady() method).
+
+ @returns the number of bytes written, or -1 if there was an error.
+ */
+ int write (const void* sourceBuffer, int numBytesToWrite);
+
+ //==============================================================================
+ /** Puts this socket into "listener" mode.
+
+ When in this mode, your thread can call waitForNextConnection() repeatedly,
+ which will spawn new sockets for each new connection, so that these can
+ be handled in parallel by other threads.
+
+ @param portNumber the port number to listen on
+ @param localHostName the interface address to listen on - pass an empty
+ string to listen on all addresses
+ @returns true if it manages to open the socket successfully.
+
+ @see waitForNextConnection
+ */
+ bool createListener (int portNumber, const String& localHostName = String());
+
+ /** When in "listener" mode, this waits for a connection and spawns it as a new
+ socket.
+
+ The object that gets returned will be owned by the caller.
+
+ This method can only be called after using createListener().
+
+ @see createListener
+ */
+ StreamingSocket* waitForNextConnection() const;
+
+private:
+ //==============================================================================
+ String hostName;
+ int volatile portNumber, handle;
+ bool connected, isListener;
+
+ StreamingSocket (const String& hostname, int portNumber, int handle);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StreamingSocket)
+};
+
+
+//==============================================================================
+/**
+ A wrapper for a datagram (UDP) socket.
+
+ This allows low-level use of sockets; for an easier-to-use messaging layer on top of
+ sockets, you could also try the InterprocessConnection class.
+
+ @see StreamingSocket, InterprocessConnection, InterprocessConnectionServer
+*/
+class JUCE_API DatagramSocket
+{
+public:
+ //==============================================================================
+ /**
+ Creates an (uninitialised) datagram socket.
+
+ The localPortNumber is the port on which to bind this socket. If this value is 0,
+ the port number is assigned by the operating system.
+
+ To use the socket for sending, call the connect() method. This will not immediately
+ make a connection, but will save the destination you've provided. After this, you can
+ call read() or write().
+
+ If enableBroadcasting is true, the socket will be allowed to send broadcast messages
+ (may require extra privileges on linux)
+
+ To wait for other sockets to connect to this one, call waitForNextConnection().
+ */
+ DatagramSocket (int localPortNumber,
+ bool enableBroadcasting = false);
+
+ /** Destructor. */
+ ~DatagramSocket();
+
+ //==============================================================================
+ /** Binds the socket to the specified local port.
+
+ @returns true on success; false may indicate that another socket is already bound
+ on the same port
+ */
+ bool bindToPort (int localPortNumber);
+
+ /** Tries to connect the socket to hostname:port.
+
+ If timeOutMillisecs is 0, then this method will block until the operating system
+ rejects the connection (which could take a long time).
+
+ @returns true if it succeeds.
+ @see isConnected
+ */
+ bool connect (const String& remoteHostname,
+ int remotePortNumber,
+ int timeOutMillisecs = 3000);
+
+ /** True if the socket is currently connected. */
+ bool isConnected() const noexcept { return connected; }
+
+ /** Closes the connection. */
+ void close();
+
+ /** Returns the name of the currently connected host. */
+ const String& getHostName() const noexcept { return hostName; }
+
+ /** Returns the port number that's currently open. */
+ int getPort() const noexcept { return portNumber; }
+
+ /** True if the socket is connected to this machine rather than over the network. */
+ bool isLocal() const noexcept;
+
+ /** Returns the OS's socket handle that's currently open. */
+ int getRawSocketHandle() const noexcept { return handle; }
+
+ //==============================================================================
+ /** Waits until the socket is ready for reading or writing.
+
+ If readyForReading is true, it will wait until the socket is ready for
+ reading; if false, it will wait until it's ready for writing.
+
+ If the timeout is < 0, it will wait forever, or else will give up after
+ the specified time.
+
+ If the socket is ready on return, this returns 1. If it times-out before
+ the socket becomes ready, it returns 0. If an error occurs, it returns -1.
+ */
+ int waitUntilReady (bool readyForReading,
+ int timeoutMsecs) const;
+
+ /** Reads bytes from the socket.
+
+ If blockUntilSpecifiedAmountHasArrived is true, the method will block until
+ maxBytesToRead bytes have been read, (or until an error occurs). If this
+ flag is false, the method will return as much data as is currently available
+ without blocking.
+
+ @returns the number of bytes read, or -1 if there was an error.
+ @see waitUntilReady
+ */
+ int read (void* destBuffer, int maxBytesToRead,
+ bool blockUntilSpecifiedAmountHasArrived);
+
+ /** Writes bytes to the socket from a buffer.
+
+ Note that this method will block unless you have checked the socket is ready
+ for writing before calling it (see the waitUntilReady() method).
+
+ @returns the number of bytes written, or -1 if there was an error.
+ */
+ int write (const void* sourceBuffer, int numBytesToWrite);
+
+ //==============================================================================
+ /** This waits for incoming data to be sent, and returns a socket that can be used
+ to read it.
+
+ The object that gets returned is owned by the caller, and can't be used for
+ sending, but can be used to read the data.
+ */
+ DatagramSocket* waitForNextConnection() const;
+
+private:
+ //==============================================================================
+ String hostName;
+ int volatile portNumber, handle;
+ bool connected, allowBroadcast;
+ void* serverAddress;
+
+ DatagramSocket (const String& hostname, int portNumber, int handle, int localPortNumber);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DatagramSocket)
+};
+
+
+#endif // JUCE_SOCKET_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.cpp
new file mode 100644
index 0000000..49db1f9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.cpp
@@ -0,0 +1,497 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+URL::URL()
+{
+}
+
+URL::URL (const String& u) : url (u)
+{
+ int i = url.indexOfChar ('?');
+
+ if (i >= 0)
+ {
+ do
+ {
+ const int nextAmp = url.indexOfChar (i + 1, '&');
+ const int equalsPos = url.indexOfChar (i + 1, '=');
+
+ if (equalsPos > i + 1)
+ {
+ if (nextAmp < 0)
+ {
+ addParameter (removeEscapeChars (url.substring (i + 1, equalsPos)),
+ removeEscapeChars (url.substring (equalsPos + 1)));
+ }
+ else if (nextAmp > 0 && equalsPos < nextAmp)
+ {
+ addParameter (removeEscapeChars (url.substring (i + 1, equalsPos)),
+ removeEscapeChars (url.substring (equalsPos + 1, nextAmp)));
+ }
+ }
+
+ i = nextAmp;
+ }
+ while (i >= 0);
+
+ url = url.upToFirstOccurrenceOf ("?", false, false);
+ }
+}
+
+URL::URL (const String& u, int) : url (u) {}
+
+URL URL::createWithoutParsing (const String& u)
+{
+ return URL (u, 0);
+}
+
+URL::URL (const URL& other)
+ : url (other.url),
+ postData (other.postData),
+ parameterNames (other.parameterNames),
+ parameterValues (other.parameterValues),
+ filesToUpload (other.filesToUpload)
+{
+}
+
+URL& URL::operator= (const URL& other)
+{
+ url = other.url;
+ postData = other.postData;
+ parameterNames = other.parameterNames;
+ parameterValues = other.parameterValues;
+ filesToUpload = other.filesToUpload;
+
+ return *this;
+}
+
+bool URL::operator== (const URL& other) const
+{
+ return url == other.url
+ && postData == other.postData
+ && parameterNames == other.parameterNames
+ && parameterValues == other.parameterValues
+ && filesToUpload == other.filesToUpload;
+}
+
+bool URL::operator!= (const URL& other) const
+{
+ return ! operator== (other);
+}
+
+URL::~URL()
+{
+}
+
+namespace URLHelpers
+{
+ static String getMangledParameters (const URL& url)
+ {
+ jassert (url.getParameterNames().size() == url.getParameterValues().size());
+ String p;
+
+ for (int i = 0; i < url.getParameterNames().size(); ++i)
+ {
+ if (i > 0)
+ p << '&';
+
+ p << URL::addEscapeChars (url.getParameterNames()[i], true)
+ << '='
+ << URL::addEscapeChars (url.getParameterValues()[i], true);
+ }
+
+ return p;
+ }
+
+ static int findEndOfScheme (const String& url)
+ {
+ int i = 0;
+
+ while (CharacterFunctions::isLetterOrDigit (url[i])
+ || url[i] == '+' || url[i] == '-' || url[i] == '.')
+ ++i;
+
+ return url[i] == ':' ? i + 1 : 0;
+ }
+
+ static int findStartOfNetLocation (const String& url)
+ {
+ int start = findEndOfScheme (url);
+ while (url[start] == '/')
+ ++start;
+
+ return start;
+ }
+
+ static int findStartOfPath (const String& url)
+ {
+ return url.indexOfChar (findStartOfNetLocation (url), '/') + 1;
+ }
+
+ static void concatenatePaths (String& path, const String& suffix)
+ {
+ if (! path.endsWithChar ('/'))
+ path << '/';
+
+ if (suffix.startsWithChar ('/'))
+ path += suffix.substring (1);
+ else
+ path += suffix;
+ }
+}
+
+void URL::addParameter (const String& name, const String& value)
+{
+ parameterNames.add (name);
+ parameterValues.add (value);
+}
+
+String URL::toString (const bool includeGetParameters) const
+{
+ if (includeGetParameters && parameterNames.size() > 0)
+ return url + "?" + URLHelpers::getMangledParameters (*this);
+
+ return url;
+}
+
+bool URL::isWellFormed() const
+{
+ //xxx TODO
+ return url.isNotEmpty();
+}
+
+String URL::getDomain() const
+{
+ const int start = URLHelpers::findStartOfNetLocation (url);
+ const int end1 = url.indexOfChar (start, '/');
+ const int end2 = url.indexOfChar (start, ':');
+
+ const int end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max()
+ : ((end1 < 0 || end2 < 0) ? jmax (end1, end2)
+ : jmin (end1, end2));
+ return url.substring (start, end);
+}
+
+String URL::getSubPath() const
+{
+ const int startOfPath = URLHelpers::findStartOfPath (url);
+
+ return startOfPath <= 0 ? String()
+ : url.substring (startOfPath);
+}
+
+String URL::getScheme() const
+{
+ return url.substring (0, URLHelpers::findEndOfScheme (url) - 1);
+}
+
+int URL::getPort() const
+{
+ const int colonPos = url.indexOfChar (URLHelpers::findStartOfNetLocation (url), ':');
+
+ return colonPos > 0 ? url.substring (colonPos + 1).getIntValue() : 0;
+}
+
+URL URL::withNewSubPath (const String& newPath) const
+{
+ const int startOfPath = URLHelpers::findStartOfPath (url);
+
+ URL u (*this);
+
+ if (startOfPath > 0)
+ u.url = url.substring (0, startOfPath);
+
+ URLHelpers::concatenatePaths (u.url, newPath);
+ return u;
+}
+
+URL URL::getChildURL (const String& subPath) const
+{
+ URL u (*this);
+ URLHelpers::concatenatePaths (u.url, subPath);
+ return u;
+}
+
+void URL::createHeadersAndPostData (String& headers, MemoryBlock& headersAndPostData) const
+{
+ MemoryOutputStream data (headersAndPostData, false);
+
+ if (filesToUpload.size() > 0)
+ {
+ // (this doesn't currently support mixing custom post-data with uploads..)
+ jassert (postData.isEmpty());
+
+ const String boundary (String::toHexString (Random::getSystemRandom().nextInt64()));
+
+ headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
+
+ data << "--" << boundary;
+
+ for (int i = 0; i < parameterNames.size(); ++i)
+ {
+ data << "\r\nContent-Disposition: form-data; name=\"" << parameterNames[i]
+ << "\"\r\n\r\n" << parameterValues[i]
+ << "\r\n--" << boundary;
+ }
+
+ for (int i = 0; i < filesToUpload.size(); ++i)
+ {
+ const Upload& f = *filesToUpload.getObjectPointerUnchecked(i);
+
+ data << "\r\nContent-Disposition: form-data; name=\"" << f.parameterName
+ << "\"; filename=\"" << f.filename << "\"\r\n";
+
+ if (f.mimeType.isNotEmpty())
+ data << "Content-Type: " << f.mimeType << "\r\n";
+
+ data << "Content-Transfer-Encoding: binary\r\n\r\n";
+
+ if (f.data != nullptr)
+ data << *f.data;
+ else
+ data << f.file;
+
+ data << "\r\n--" << boundary;
+ }
+
+ data << "--\r\n";
+ }
+ else
+ {
+ data << URLHelpers::getMangledParameters (*this)
+ << postData;
+
+ // if the user-supplied headers didn't contain a content-type, add one now..
+ if (! headers.containsIgnoreCase ("Content-Type"))
+ headers << "Content-Type: application/x-www-form-urlencoded\r\n";
+
+ headers << "Content-length: " << (int) data.getDataSize() << "\r\n";
+ }
+}
+
+//==============================================================================
+bool URL::isProbablyAWebsiteURL (const String& possibleURL)
+{
+ static const char* validProtocols[] = { "http:", "ftp:", "https:" };
+
+ for (int i = 0; i < numElementsInArray (validProtocols); ++i)
+ if (possibleURL.startsWithIgnoreCase (validProtocols[i]))
+ return true;
+
+ if (possibleURL.containsChar ('@')
+ || possibleURL.containsChar (' '))
+ return false;
+
+ const String topLevelDomain (possibleURL.upToFirstOccurrenceOf ("/", false, false)
+ .fromLastOccurrenceOf (".", false, false));
+
+ return topLevelDomain.isNotEmpty() && topLevelDomain.length() <= 3;
+}
+
+bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress)
+{
+ const int atSign = possibleEmailAddress.indexOfChar ('@');
+
+ return atSign > 0
+ && possibleEmailAddress.lastIndexOfChar ('.') > (atSign + 1)
+ && ! possibleEmailAddress.endsWithChar ('.');
+}
+
+//==============================================================================
+InputStream* URL::createInputStream (const bool usePostCommand,
+ OpenStreamProgressCallback* const progressCallback,
+ void* const progressCallbackContext,
+ String headers,
+ const int timeOutMs,
+ StringPairArray* const responseHeaders,
+ int* statusCode) const
+{
+ MemoryBlock headersAndPostData;
+
+ if (! headers.endsWithChar ('\n'))
+ headers << "\r\n";
+
+ if (usePostCommand)
+ createHeadersAndPostData (headers, headersAndPostData);
+
+ if (! headers.endsWithChar ('\n'))
+ headers << "\r\n";
+
+ ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand),
+ usePostCommand, headersAndPostData,
+ progressCallback, progressCallbackContext,
+ headers, timeOutMs, responseHeaders));
+
+ if (statusCode != nullptr)
+ *statusCode = wi->statusCode;
+
+ return wi->isError() ? nullptr : wi.release();
+}
+
+//==============================================================================
+bool URL::readEntireBinaryStream (MemoryBlock& destData,
+ const bool usePostCommand) const
+{
+ const ScopedPointer<InputStream> in (createInputStream (usePostCommand));
+
+ if (in != nullptr)
+ {
+ in->readIntoMemoryBlock (destData);
+ return true;
+ }
+
+ return false;
+}
+
+String URL::readEntireTextStream (const bool usePostCommand) const
+{
+ const ScopedPointer<InputStream> in (createInputStream (usePostCommand));
+
+ if (in != nullptr)
+ return in->readEntireStreamAsString();
+
+ return String();
+}
+
+XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const
+{
+ return XmlDocument::parse (readEntireTextStream (usePostCommand));
+}
+
+//==============================================================================
+URL URL::withParameter (const String& parameterName,
+ const String& parameterValue) const
+{
+ URL u (*this);
+ u.addParameter (parameterName, parameterValue);
+ return u;
+}
+
+URL URL::withPOSTData (const String& newPostData) const
+{
+ URL u (*this);
+ u.postData = newPostData;
+ return u;
+}
+
+URL::Upload::Upload (const String& param, const String& name,
+ const String& mime, const File& f, MemoryBlock* mb)
+ : parameterName (param), filename (name), mimeType (mime), file (f), data (mb)
+{
+ jassert (mimeType.isNotEmpty()); // You need to supply a mime type!
+}
+
+URL URL::withUpload (Upload* const f) const
+{
+ URL u (*this);
+
+ for (int i = u.filesToUpload.size(); --i >= 0;)
+ if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName)
+ u.filesToUpload.remove (i);
+
+ u.filesToUpload.add (f);
+ return u;
+}
+
+URL URL::withFileToUpload (const String& parameterName, const File& fileToUpload,
+ const String& mimeType) const
+{
+ return withUpload (new Upload (parameterName, fileToUpload.getFileName(),
+ mimeType, fileToUpload, nullptr));
+}
+
+URL URL::withDataToUpload (const String& parameterName, const String& filename,
+ const MemoryBlock& fileContentToUpload, const String& mimeType) const
+{
+ return withUpload (new Upload (parameterName, filename, mimeType, File(),
+ new MemoryBlock (fileContentToUpload)));
+}
+
+//==============================================================================
+String URL::removeEscapeChars (const String& s)
+{
+ String result (s.replaceCharacter ('+', ' '));
+
+ if (! result.containsChar ('%'))
+ return result;
+
+ // We need to operate on the string as raw UTF8 chars, and then recombine them into unicode
+ // after all the replacements have been made, so that multi-byte chars are handled.
+ Array<char> utf8 (result.toRawUTF8(), (int) result.getNumBytesAsUTF8());
+
+ for (int i = 0; i < utf8.size(); ++i)
+ {
+ if (utf8.getUnchecked(i) == '%')
+ {
+ const int hexDigit1 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 1]);
+ const int hexDigit2 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 2]);
+
+ if (hexDigit1 >= 0 && hexDigit2 >= 0)
+ {
+ utf8.set (i, (char) ((hexDigit1 << 4) + hexDigit2));
+ utf8.removeRange (i + 1, 2);
+ }
+ }
+ }
+
+ return String::fromUTF8 (utf8.getRawDataPointer(), utf8.size());
+}
+
+String URL::addEscapeChars (const String& s, const bool isParameter)
+{
+ const CharPointer_UTF8 legalChars (isParameter ? "_-.*!'()"
+ : ",$_-.*!'()");
+
+ Array<char> utf8 (s.toRawUTF8(), (int) s.getNumBytesAsUTF8());
+
+ for (int i = 0; i < utf8.size(); ++i)
+ {
+ const char c = utf8.getUnchecked(i);
+
+ if (! (CharacterFunctions::isLetterOrDigit (c)
+ || legalChars.indexOf ((juce_wchar) c) >= 0))
+ {
+ utf8.set (i, '%');
+ utf8.insert (++i, "0123456789abcdef" [((uint8) c) >> 4]);
+ utf8.insert (++i, "0123456789abcdef" [c & 15]);
+ }
+ }
+
+ return String::fromUTF8 (utf8.getRawDataPointer(), utf8.size());
+}
+
+//==============================================================================
+bool URL::launchInDefaultBrowser() const
+{
+ String u (toString (true));
+
+ if (u.containsChar ('@') && ! u.containsChar (':'))
+ u = "mailto:" + u;
+
+ return Process::openDocument (u, String());
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.h b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.h
new file mode 100644
index 0000000..4f511d8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/network/juce_URL.h
@@ -0,0 +1,375 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_URL_H_INCLUDED
+#define JUCE_URL_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a URL and has a bunch of useful functions to manipulate it.
+
+ This class can be used to launch URLs in browsers, and also to create
+ InputStreams that can read from remote http or ftp sources.
+*/
+class JUCE_API URL
+{
+public:
+ //==============================================================================
+ /** Creates an empty URL. */
+ URL();
+
+ /** Creates a URL from a string.
+ This will parse any embedded parameters after a '?' character and store them
+ in the list (see getParameterNames etc). If you don't want this to happen, you
+ can use createWithoutParsing().
+ */
+ URL (const String& url);
+
+ /** Creates a copy of another URL. */
+ URL (const URL& other);
+
+ /** Destructor. */
+ ~URL();
+
+ /** Copies this URL from another one. */
+ URL& operator= (const URL& other);
+
+ /** Compares two URLs.
+ All aspects of the URLs must be identical for them to match, including any parameters,
+ upload files, etc.
+ */
+ bool operator== (const URL&) const;
+ bool operator!= (const URL&) const;
+
+ //==============================================================================
+ /** Returns a string version of the URL.
+
+ If includeGetParameters is true and any parameters have been set with the
+ withParameter() method, then the string will have these appended on the
+ end and url-encoded.
+ */
+ String toString (bool includeGetParameters) const;
+
+ /** True if it seems to be valid. */
+ bool isWellFormed() const;
+
+ /** Returns just the domain part of the URL.
+
+ E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com".
+ */
+ String getDomain() const;
+
+ /** Returns the path part of the URL.
+
+ E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar".
+ */
+ String getSubPath() const;
+
+ /** Returns the scheme of the URL.
+
+ E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't
+ include the colon).
+ */
+ String getScheme() const;
+
+ /** Attempts to read a port number from the URL.
+ @returns the port number, or 0 if none is explicitly specified.
+ */
+ int getPort() const;
+
+ /** Returns a new version of this URL that uses a different sub-path.
+
+ E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with
+ "bar", it'll return "http://www.xyz.com/bar?x=1".
+ */
+ URL withNewSubPath (const String& newPath) const;
+
+ /** Returns a new URL that refers to a sub-path relative to this one.
+
+ E.g. if the URL is "http://www.xyz.com/foo" and you call this with
+ "bar", it'll return "http://www.xyz.com/foo/bar". Note that there's no way for
+ this method to know whether the original URL is a file or directory, so it's
+ up to you to make sure it's a directory. It also won't attempt to be smart about
+ the content of the childPath string, so if this string is an absolute URL, it'll
+ still just get bolted onto the end of the path.
+
+ @see File::getChildFile
+ */
+ URL getChildURL (const String& subPath) const;
+
+ //==============================================================================
+ /** Returns a copy of this URL, with a GET or POST parameter added to the end.
+
+ Any control characters in the value will be encoded.
+
+ e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com"
+ would produce a new url whose toString(true) method would return
+ "www.fish.com?amount=some+fish".
+
+ @see getParameterNames, getParameterValues
+ */
+ URL withParameter (const String& parameterName,
+ const String& parameterValue) const;
+
+ /** Returns a copy of this URL, with a file-upload type parameter added to it.
+
+ When performing a POST where one of your parameters is a binary file, this
+ lets you specify the file.
+
+ Note that the filename is stored, but the file itself won't actually be read
+ until this URL is later used to create a network input stream. If you want to
+ upload data from memory, use withDataToUpload().
+
+ @see withDataToUpload
+ */
+ URL withFileToUpload (const String& parameterName,
+ const File& fileToUpload,
+ const String& mimeType) const;
+
+ /** Returns a copy of this URL, with a file-upload type parameter added to it.
+
+ When performing a POST where one of your parameters is a binary file, this
+ lets you specify the file content.
+ Note that the filename parameter should not be a full path, it's just the
+ last part of the filename.
+
+ @see withFileToUpload
+ */
+ URL withDataToUpload (const String& parameterName,
+ const String& filename,
+ const MemoryBlock& fileContentToUpload,
+ const String& mimeType) const;
+
+ /** Returns an array of the names of all the URL's parameters.
+
+ E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would
+ contain two items: "type" and "amount".
+
+ You can call getParameterValues() to get the corresponding value of each
+ parameter. Note that the list can contain multiple parameters with the same name.
+
+ @see getParameterValues, withParameter
+ */
+ const StringArray& getParameterNames() const noexcept { return parameterNames; }
+
+ /** Returns an array of the values of all the URL's parameters.
+
+ E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would
+ contain two items: "haddock" and "some fish".
+
+ The values returned will have been cleaned up to remove any escape characters.
+
+ You can call getParameterNames() to get the corresponding name of each
+ parameter. Note that the list can contain multiple parameters with the same name.
+
+ @see getParameterNames, withParameter
+ */
+ const StringArray& getParameterValues() const noexcept { return parameterValues; }
+
+ /** Returns a copy of this URL, with a block of data to send as the POST data.
+
+ If you're setting the POST data, be careful not to have any parameters set
+ as well, otherwise it'll all get thrown in together, and might not have the
+ desired effect.
+
+ If the URL already contains some POST data, this will replace it, rather
+ than being appended to it.
+
+ This data will only be used if you specify a post operation when you call
+ createInputStream().
+ */
+ URL withPOSTData (const String& postData) const;
+
+ /** Returns the data that was set using withPOSTData(). */
+ const String& getPostData() const noexcept { return postData; }
+
+ //==============================================================================
+ /** Tries to launch the system's default browser to open the URL.
+
+ Returns true if this seems to have worked.
+ */
+ bool launchInDefaultBrowser() const;
+
+ //==============================================================================
+ /** Takes a guess as to whether a string might be a valid website address.
+
+ This isn't foolproof!
+ */
+ static bool isProbablyAWebsiteURL (const String& possibleURL);
+
+ /** Takes a guess as to whether a string might be a valid email address.
+
+ This isn't foolproof!
+ */
+ static bool isProbablyAnEmailAddress (const String& possibleEmailAddress);
+
+ //==============================================================================
+ /** This callback function can be used by the createInputStream() method.
+
+ It allows your app to receive progress updates during a lengthy POST operation. If you
+ want to continue the operation, this should return true, or false to abort.
+ */
+ typedef bool (OpenStreamProgressCallback) (void* context, int bytesSent, int totalBytes);
+
+ /** Attempts to open a stream that can read from this URL.
+
+ @param usePostCommand if true, it will try to do use a http 'POST' to pass
+ the parameters, otherwise it'll encode them into the
+ URL and do a 'GET'.
+ @param progressCallback if this is non-zero, it lets you supply a callback function
+ to keep track of the operation's progress. This can be useful
+ for lengthy POST operations, so that you can provide user feedback.
+ @param progressCallbackContext if a callback is specified, this value will be passed to
+ the function
+ @param extraHeaders if not empty, this string is appended onto the headers that
+ are used for the request. It must therefore be a valid set of HTML
+ header directives, separated by newlines.
+ @param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If
+ a negative number, it will be infinite. Otherwise it specifies a
+ time in milliseconds.
+ @param responseHeaders if this is non-null, all the (key, value) pairs received as headers
+ in the response will be stored in this array
+ @param statusCode if this is non-null, it will get set to the http status code, if one
+ is known, or 0 if a code isn't available
+ @returns an input stream that the caller must delete, or a null pointer if there was an
+ error trying to open it.
+ */
+ InputStream* createInputStream (bool usePostCommand,
+ OpenStreamProgressCallback* progressCallback = nullptr,
+ void* progressCallbackContext = nullptr,
+ String extraHeaders = String(),
+ int connectionTimeOutMs = 0,
+ StringPairArray* responseHeaders = nullptr,
+ int* statusCode = nullptr) const;
+
+
+ //==============================================================================
+ /** Tries to download the entire contents of this URL into a binary data block.
+
+ If it succeeds, this will return true and append the data it read onto the end
+ of the memory block.
+
+ @param destData the memory block to append the new data to
+ @param usePostCommand whether to use a POST command to get the data (uses
+ a GET command if this is false)
+ @see readEntireTextStream, readEntireXmlStream
+ */
+ bool readEntireBinaryStream (MemoryBlock& destData,
+ bool usePostCommand = false) const;
+
+ /** Tries to download the entire contents of this URL as a string.
+
+ If it fails, this will return an empty string, otherwise it will return the
+ contents of the downloaded file. If you need to distinguish between a read
+ operation that fails and one that returns an empty string, you'll need to use
+ a different method, such as readEntireBinaryStream().
+
+ @param usePostCommand whether to use a POST command to get the data (uses
+ a GET command if this is false)
+ @see readEntireBinaryStream, readEntireXmlStream
+ */
+ String readEntireTextStream (bool usePostCommand = false) const;
+
+ /** Tries to download the entire contents of this URL and parse it as XML.
+
+ If it fails, or if the text that it reads can't be parsed as XML, this will
+ return 0.
+
+ When it returns a valid XmlElement object, the caller is responsibile for deleting
+ this object when no longer needed.
+
+ @param usePostCommand whether to use a POST command to get the data (uses
+ a GET command if this is false)
+
+ @see readEntireBinaryStream, readEntireTextStream
+ */
+ XmlElement* readEntireXmlStream (bool usePostCommand = false) const;
+
+ //==============================================================================
+ /** Adds escape sequences to a string to encode any characters that aren't
+ legal in a URL.
+
+ E.g. any spaces will be replaced with "%20".
+
+ This is the opposite of removeEscapeChars().
+
+ If isParameter is true, it means that the string is going to be used
+ as a parameter, so it also encodes '$' and ',' (which would otherwise
+ be legal in a URL.
+
+ @see removeEscapeChars
+ */
+ static String addEscapeChars (const String& stringToAddEscapeCharsTo,
+ bool isParameter);
+
+ /** Replaces any escape character sequences in a string with their original
+ character codes.
+
+ E.g. any instances of "%20" will be replaced by a space.
+
+ This is the opposite of addEscapeChars().
+
+ @see addEscapeChars
+ */
+ static String removeEscapeChars (const String& stringToRemoveEscapeCharsFrom);
+
+ /** Returns a URL without attempting to remove any embedded parameters from the string.
+ This may be necessary if you need to create a request that involves both POST
+ parameters and parameters which are embedded in the URL address itself.
+ */
+ static URL createWithoutParsing (const String& url);
+
+private:
+ //==============================================================================
+ String url, postData;
+ StringArray parameterNames, parameterValues;
+
+ struct Upload : public ReferenceCountedObject
+ {
+ Upload (const String&, const String&, const String&, const File&, MemoryBlock*);
+ String parameterName, filename, mimeType;
+ File file;
+ ScopedPointer<MemoryBlock> data;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Upload)
+ };
+
+ friend struct ContainerDeletePolicy<Upload>;
+ ReferenceCountedArray<Upload> filesToUpload;
+
+ URL (const String&, int);
+ void addParameter (const String&, const String&);
+ void createHeadersAndPostData (String&, MemoryBlock&) const;
+ URL withUpload (Upload*) const;
+
+ JUCE_LEAK_DETECTOR (URL)
+};
+
+
+#endif // JUCE_URL_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.cpp
new file mode 100644
index 0000000..ec01f8e
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.cpp
@@ -0,0 +1,198 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+namespace
+{
+ int calcBufferStreamBufferSize (int requestedSize, InputStream* const source) noexcept
+ {
+ // You need to supply a real stream when creating a BufferedInputStream
+ jassert (source != nullptr);
+
+ requestedSize = jmax (256, requestedSize);
+
+ const int64 sourceSize = source->getTotalLength();
+ if (sourceSize >= 0 && sourceSize < requestedSize)
+ requestedSize = jmax (32, (int) sourceSize);
+
+ return requestedSize;
+ }
+}
+
+//==============================================================================
+BufferedInputStream::BufferedInputStream (InputStream* const sourceStream, const int bufferSize_,
+ const bool deleteSourceWhenDestroyed)
+ : source (sourceStream, deleteSourceWhenDestroyed),
+ bufferSize (calcBufferStreamBufferSize (bufferSize_, sourceStream)),
+ position (sourceStream->getPosition()),
+ lastReadPos (0),
+ bufferStart (position),
+ bufferOverlap (128)
+{
+ buffer.malloc ((size_t) bufferSize);
+}
+
+BufferedInputStream::BufferedInputStream (InputStream& sourceStream, const int bufferSize_)
+ : source (&sourceStream, false),
+ bufferSize (calcBufferStreamBufferSize (bufferSize_, &sourceStream)),
+ position (sourceStream.getPosition()),
+ lastReadPos (0),
+ bufferStart (position),
+ bufferOverlap (128)
+{
+ buffer.malloc ((size_t) bufferSize);
+}
+
+BufferedInputStream::~BufferedInputStream()
+{
+}
+
+//==============================================================================
+int64 BufferedInputStream::getTotalLength()
+{
+ return source->getTotalLength();
+}
+
+int64 BufferedInputStream::getPosition()
+{
+ return position;
+}
+
+bool BufferedInputStream::setPosition (int64 newPosition)
+{
+ position = jmax ((int64) 0, newPosition);
+ return true;
+}
+
+bool BufferedInputStream::isExhausted()
+{
+ return position >= lastReadPos && source->isExhausted();
+}
+
+void BufferedInputStream::ensureBuffered()
+{
+ const int64 bufferEndOverlap = lastReadPos - bufferOverlap;
+
+ if (position < bufferStart || position >= bufferEndOverlap)
+ {
+ int bytesRead;
+
+ if (position < lastReadPos
+ && position >= bufferEndOverlap
+ && position >= bufferStart)
+ {
+ const int bytesToKeep = (int) (lastReadPos - position);
+ memmove (buffer, buffer + (int) (position - bufferStart), (size_t) bytesToKeep);
+
+ bufferStart = position;
+
+ bytesRead = source->read (buffer + bytesToKeep,
+ (int) (bufferSize - bytesToKeep));
+
+ lastReadPos += bytesRead;
+ bytesRead += bytesToKeep;
+ }
+ else
+ {
+ bufferStart = position;
+ source->setPosition (bufferStart);
+ bytesRead = source->read (buffer, bufferSize);
+ lastReadPos = bufferStart + bytesRead;
+ }
+
+ while (bytesRead < bufferSize)
+ buffer [bytesRead++] = 0;
+ }
+}
+
+int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
+{
+ jassert (destBuffer != nullptr && maxBytesToRead >= 0);
+
+ if (position >= bufferStart
+ && position + maxBytesToRead <= lastReadPos)
+ {
+ memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) maxBytesToRead);
+ position += maxBytesToRead;
+
+ return maxBytesToRead;
+ }
+ else
+ {
+ if (position < bufferStart || position >= lastReadPos)
+ ensureBuffered();
+
+ int bytesRead = 0;
+
+ while (maxBytesToRead > 0)
+ {
+ const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position));
+
+ if (bytesAvailable > 0)
+ {
+ memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) bytesAvailable);
+ maxBytesToRead -= bytesAvailable;
+ bytesRead += bytesAvailable;
+ position += bytesAvailable;
+ destBuffer = static_cast <char*> (destBuffer) + bytesAvailable;
+ }
+
+ const int64 oldLastReadPos = lastReadPos;
+ ensureBuffered();
+
+ if (oldLastReadPos == lastReadPos)
+ break; // if ensureBuffered() failed to read any more data, bail out
+
+ if (isExhausted())
+ break;
+ }
+
+ return bytesRead;
+ }
+}
+
+String BufferedInputStream::readString()
+{
+ if (position >= bufferStart
+ && position < lastReadPos)
+ {
+ const int maxChars = (int) (lastReadPos - position);
+
+ const char* const src = buffer + (int) (position - bufferStart);
+
+ for (int i = 0; i < maxChars; ++i)
+ {
+ if (src[i] == 0)
+ {
+ position += i + 1;
+ return String::fromUTF8 (src, i);
+ }
+ }
+ }
+
+ return InputStream::readString();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.h
new file mode 100644
index 0000000..8f1e633
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_BufferedInputStream.h
@@ -0,0 +1,92 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_BUFFEREDINPUTSTREAM_H_INCLUDED
+#define JUCE_BUFFEREDINPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/** Wraps another input stream, and reads from it using an intermediate buffer
+
+ If you're using an input stream such as a file input stream, and making lots of
+ small read accesses to it, it's probably sensible to wrap it in one of these,
+ so that the source stream gets accessed in larger chunk sizes, meaning less
+ work for the underlying stream.
+*/
+class JUCE_API BufferedInputStream : public InputStream
+{
+public:
+ //==============================================================================
+ /** Creates a BufferedInputStream from an input source.
+
+ @param sourceStream the source stream to read from
+ @param bufferSize the size of reservoir to use to buffer the source
+ @param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be
+ deleted by this object when it is itself deleted.
+ */
+ BufferedInputStream (InputStream* sourceStream,
+ int bufferSize,
+ bool deleteSourceWhenDestroyed);
+
+ /** Creates a BufferedInputStream from an input source.
+
+ @param sourceStream the source stream to read from - the source stream must not
+ be deleted until this object has been destroyed.
+ @param bufferSize the size of reservoir to use to buffer the source
+ */
+ BufferedInputStream (InputStream& sourceStream, int bufferSize);
+
+ /** Destructor.
+
+ This may also delete the source stream, if that option was chosen when the
+ buffered stream was created.
+ */
+ ~BufferedInputStream();
+
+
+ //==============================================================================
+ int64 getTotalLength() override;
+ int64 getPosition() override;
+ bool setPosition (int64 newPosition) override;
+ int read (void* destBuffer, int maxBytesToRead) override;
+ String readString() override;
+ bool isExhausted() override;
+
+
+private:
+ //==============================================================================
+ OptionalScopedPointer<InputStream> source;
+ int bufferSize;
+ int64 position, lastReadPos, bufferStart, bufferOverlap;
+ HeapBlock <char> buffer;
+ void ensureBuffered();
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BufferedInputStream)
+};
+
+#endif // JUCE_BUFFEREDINPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.cpp
new file mode 100644
index 0000000..51b9db9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.cpp
@@ -0,0 +1,56 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+FileInputSource::FileInputSource (const File& f, bool useFileTimeInHash)
+ : file (f), useFileTimeInHashGeneration (useFileTimeInHash)
+{
+}
+
+FileInputSource::~FileInputSource()
+{
+}
+
+InputStream* FileInputSource::createInputStream()
+{
+ return file.createInputStream();
+}
+
+InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPath)
+{
+ return file.getSiblingFile (relatedItemPath).createInputStream();
+}
+
+int64 FileInputSource::hashCode() const
+{
+ int64 h = file.hashCode();
+
+ if (useFileTimeInHashGeneration)
+ h ^= file.getLastModificationTime().toMilliseconds();
+
+ return h;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.h
new file mode 100644
index 0000000..d2e6d86
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_FileInputSource.h
@@ -0,0 +1,66 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_FILEINPUTSOURCE_H_INCLUDED
+#define JUCE_FILEINPUTSOURCE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A type of InputSource that represents a normal file.
+
+ @see InputSource
+*/
+class JUCE_API FileInputSource : public InputSource
+{
+public:
+ //==============================================================================
+ /** Creates a FileInputSource for a file.
+ If the useFileTimeInHashGeneration parameter is true, then this object's
+ hashCode() method will incorporate the file time into its hash code; if
+ false, only the file name will be used for the hash.
+ */
+ FileInputSource (const File& file, bool useFileTimeInHashGeneration = false);
+
+ /** Destructor. */
+ ~FileInputSource();
+
+ InputStream* createInputStream();
+ InputStream* createInputStreamFor (const String& relatedItemPath);
+ int64 hashCode() const;
+
+private:
+ //==============================================================================
+ const File file;
+ bool useFileTimeInHashGeneration;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileInputSource)
+};
+
+
+#endif // JUCE_FILEINPUTSOURCE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputSource.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputSource.h
new file mode 100644
index 0000000..0e13ac5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputSource.h
@@ -0,0 +1,78 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_INPUTSOURCE_H_INCLUDED
+#define JUCE_INPUTSOURCE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A lightweight object that can create a stream to read some kind of resource.
+
+ This may be used to refer to a file, or some other kind of source, allowing a
+ caller to create an input stream that can read from it when required.
+
+ @see FileInputSource
+*/
+class JUCE_API InputSource
+{
+public:
+ //==============================================================================
+ InputSource() noexcept {}
+
+ /** Destructor. */
+ virtual ~InputSource() {}
+
+ //==============================================================================
+ /** Returns a new InputStream to read this item.
+
+ @returns an inputstream that the caller will delete, or nullptr if
+ the filename isn't found.
+ */
+ virtual InputStream* createInputStream() = 0;
+
+ /** Returns a new InputStream to read an item, relative.
+
+ @param relatedItemPath the relative pathname of the resource that is required
+ @returns an inputstream that the caller will delete, or nullptr if
+ the item isn't found.
+ */
+ virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0;
+
+ /** Returns a hash code that uniquely represents this item.
+ */
+ virtual int64 hashCode() const = 0;
+
+
+private:
+ //==============================================================================
+ JUCE_LEAK_DETECTOR (InputSource)
+};
+
+
+#endif // JUCE_INPUTSOURCE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.cpp
new file mode 100644
index 0000000..07b9976
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.cpp
@@ -0,0 +1,236 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+int64 InputStream::getNumBytesRemaining()
+{
+ int64 len = getTotalLength();
+
+ if (len >= 0)
+ len -= getPosition();
+
+ return len;
+}
+
+char InputStream::readByte()
+{
+ char temp = 0;
+ read (&temp, 1);
+ return temp;
+}
+
+bool InputStream::readBool()
+{
+ return readByte() != 0;
+}
+
+short InputStream::readShort()
+{
+ char temp[2];
+
+ if (read (temp, 2) == 2)
+ return (short) ByteOrder::littleEndianShort (temp);
+
+ return 0;
+}
+
+short InputStream::readShortBigEndian()
+{
+ char temp[2];
+
+ if (read (temp, 2) == 2)
+ return (short) ByteOrder::bigEndianShort (temp);
+
+ return 0;
+}
+
+int InputStream::readInt()
+{
+ char temp[4];
+
+ if (read (temp, 4) == 4)
+ return (int) ByteOrder::littleEndianInt (temp);
+
+ return 0;
+}
+
+int InputStream::readIntBigEndian()
+{
+ char temp[4];
+
+ if (read (temp, 4) == 4)
+ return (int) ByteOrder::bigEndianInt (temp);
+
+ return 0;
+}
+
+int InputStream::readCompressedInt()
+{
+ const uint8 sizeByte = (uint8) readByte();
+ if (sizeByte == 0)
+ return 0;
+
+ const int numBytes = (sizeByte & 0x7f);
+ if (numBytes > 4)
+ {
+ jassertfalse; // trying to read corrupt data - this method must only be used
+ // to read data that was written by OutputStream::writeCompressedInt()
+ return 0;
+ }
+
+ char bytes[4] = { 0, 0, 0, 0 };
+ if (read (bytes, numBytes) != numBytes)
+ return 0;
+
+ const int num = (int) ByteOrder::littleEndianInt (bytes);
+ return (sizeByte >> 7) ? -num : num;
+}
+
+int64 InputStream::readInt64()
+{
+ union { uint8 asBytes[8]; uint64 asInt64; } n;
+
+ if (read (n.asBytes, 8) == 8)
+ return (int64) ByteOrder::swapIfBigEndian (n.asInt64);
+
+ return 0;
+}
+
+int64 InputStream::readInt64BigEndian()
+{
+ union { uint8 asBytes[8]; uint64 asInt64; } n;
+
+ if (read (n.asBytes, 8) == 8)
+ return (int64) ByteOrder::swapIfLittleEndian (n.asInt64);
+
+ return 0;
+}
+
+float InputStream::readFloat()
+{
+ // the union below relies on these types being the same size...
+ static_jassert (sizeof (int32) == sizeof (float));
+ union { int32 asInt; float asFloat; } n;
+ n.asInt = (int32) readInt();
+ return n.asFloat;
+}
+
+float InputStream::readFloatBigEndian()
+{
+ union { int32 asInt; float asFloat; } n;
+ n.asInt = (int32) readIntBigEndian();
+ return n.asFloat;
+}
+
+double InputStream::readDouble()
+{
+ union { int64 asInt; double asDouble; } n;
+ n.asInt = readInt64();
+ return n.asDouble;
+}
+
+double InputStream::readDoubleBigEndian()
+{
+ union { int64 asInt; double asDouble; } n;
+ n.asInt = readInt64BigEndian();
+ return n.asDouble;
+}
+
+String InputStream::readString()
+{
+ MemoryBlock buffer (256);
+ char* data = static_cast<char*> (buffer.getData());
+ size_t i = 0;
+
+ while ((data[i] = readByte()) != 0)
+ {
+ if (++i >= buffer.getSize())
+ {
+ buffer.setSize (buffer.getSize() + 512);
+ data = static_cast<char*> (buffer.getData());
+ }
+ }
+
+ return String::fromUTF8 (data, (int) i);
+}
+
+String InputStream::readNextLine()
+{
+ MemoryBlock buffer (256);
+ char* data = static_cast<char*> (buffer.getData());
+ size_t i = 0;
+
+ while ((data[i] = readByte()) != 0)
+ {
+ if (data[i] == '\n')
+ break;
+
+ if (data[i] == '\r')
+ {
+ const int64 lastPos = getPosition();
+
+ if (readByte() != '\n')
+ setPosition (lastPos);
+
+ break;
+ }
+
+ if (++i >= buffer.getSize())
+ {
+ buffer.setSize (buffer.getSize() + 512);
+ data = static_cast<char*> (buffer.getData());
+ }
+ }
+
+ return String::fromUTF8 (data, (int) i);
+}
+
+size_t InputStream::readIntoMemoryBlock (MemoryBlock& block, ssize_t numBytes)
+{
+ MemoryOutputStream mo (block, true);
+ return (size_t) mo.writeFromInputStream (*this, numBytes);
+}
+
+String InputStream::readEntireStreamAsString()
+{
+ MemoryOutputStream mo;
+ mo << *this;
+ return mo.toString();
+}
+
+//==============================================================================
+void InputStream::skipNextBytes (int64 numBytesToSkip)
+{
+ if (numBytesToSkip > 0)
+ {
+ const int skipBufferSize = (int) jmin (numBytesToSkip, (int64) 16384);
+ HeapBlock<char> temp ((size_t) skipBufferSize);
+
+ while (numBytesToSkip > 0 && ! isExhausted())
+ numBytesToSkip -= read (temp, (int) jmin (numBytesToSkip, (int64) skipBufferSize));
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.h
new file mode 100644
index 0000000..ebdc795
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_InputStream.h
@@ -0,0 +1,266 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_INPUTSTREAM_H_INCLUDED
+#define JUCE_INPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/** The base class for streams that read data.
+
+ Input and output streams are used throughout the library - subclasses can override
+ some or all of the virtual functions to implement their behaviour.
+
+ @see OutputStream, MemoryInputStream, BufferedInputStream, FileInputStream
+*/
+class JUCE_API InputStream
+{
+public:
+ /** Destructor. */
+ virtual ~InputStream() {}
+
+ //==============================================================================
+ /** Returns the total number of bytes available for reading in this stream.
+
+ Note that this is the number of bytes available from the start of the
+ stream, not from the current position.
+
+ If the size of the stream isn't actually known, this will return -1.
+
+ @see getNumBytesRemaining
+ */
+ virtual int64 getTotalLength() = 0;
+
+ /** Returns the number of bytes available for reading, or a negative value if
+ the remaining length is not known.
+ @see getTotalLength
+ */
+ int64 getNumBytesRemaining();
+
+ /** Returns true if the stream has no more data to read. */
+ virtual bool isExhausted() = 0;
+
+ //==============================================================================
+ /** Reads some data from the stream into a memory buffer.
+
+ This is the only read method that subclasses actually need to implement, as the
+ InputStream base class implements the other read methods in terms of this one (although
+ it's often more efficient for subclasses to implement them directly).
+
+ @param destBuffer the destination buffer for the data. This must not be null.
+ @param maxBytesToRead the maximum number of bytes to read - make sure the
+ memory block passed in is big enough to contain this
+ many bytes. This value must not be negative.
+
+ @returns the actual number of bytes that were read, which may be less than
+ maxBytesToRead if the stream is exhausted before it gets that far
+ */
+ virtual int read (void* destBuffer, int maxBytesToRead) = 0;
+
+ /** Reads a byte from the stream.
+ If the stream is exhausted, this will return zero.
+ @see OutputStream::writeByte
+ */
+ virtual char readByte();
+
+ /** Reads a boolean from the stream.
+ The bool is encoded as a single byte - non-zero for true, 0 for false.
+ If the stream is exhausted, this will return false.
+ @see OutputStream::writeBool
+ */
+ virtual bool readBool();
+
+ /** Reads two bytes from the stream as a little-endian 16-bit value.
+ If the next two bytes read are byte1 and byte2, this returns (byte1 | (byte2 << 8)).
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeShort, readShortBigEndian
+ */
+ virtual short readShort();
+
+ /** Reads two bytes from the stream as a little-endian 16-bit value.
+ If the next two bytes read are byte1 and byte2, this returns (byte2 | (byte1 << 8)).
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeShortBigEndian, readShort
+ */
+ virtual short readShortBigEndian();
+
+ /** Reads four bytes from the stream as a little-endian 32-bit value.
+
+ If the next four bytes are byte1 to byte4, this returns
+ (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)).
+
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+
+ @see OutputStream::writeInt, readIntBigEndian
+ */
+ virtual int readInt();
+
+ /** Reads four bytes from the stream as a big-endian 32-bit value.
+
+ If the next four bytes are byte1 to byte4, this returns
+ (byte4 | (byte3 << 8) | (byte2 << 16) | (byte1 << 24)).
+
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+
+ @see OutputStream::writeIntBigEndian, readInt
+ */
+ virtual int readIntBigEndian();
+
+ /** Reads eight bytes from the stream as a little-endian 64-bit value.
+
+ If the next eight bytes are byte1 to byte8, this returns
+ (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24) | (byte5 << 32) | (byte6 << 40) | (byte7 << 48) | (byte8 << 56)).
+
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+
+ @see OutputStream::writeInt64, readInt64BigEndian
+ */
+ virtual int64 readInt64();
+
+ /** Reads eight bytes from the stream as a big-endian 64-bit value.
+
+ If the next eight bytes are byte1 to byte8, this returns
+ (byte8 | (byte7 << 8) | (byte6 << 16) | (byte5 << 24) | (byte4 << 32) | (byte3 << 40) | (byte2 << 48) | (byte1 << 56)).
+
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+
+ @see OutputStream::writeInt64BigEndian, readInt64
+ */
+ virtual int64 readInt64BigEndian();
+
+ /** Reads four bytes as a 32-bit floating point value.
+ The raw 32-bit encoding of the float is read from the stream as a little-endian int.
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeFloat, readDouble
+ */
+ virtual float readFloat();
+
+ /** Reads four bytes as a 32-bit floating point value.
+ The raw 32-bit encoding of the float is read from the stream as a big-endian int.
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeFloatBigEndian, readDoubleBigEndian
+ */
+ virtual float readFloatBigEndian();
+
+ /** Reads eight bytes as a 64-bit floating point value.
+ The raw 64-bit encoding of the double is read from the stream as a little-endian int64.
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeDouble, readFloat
+ */
+ virtual double readDouble();
+
+ /** Reads eight bytes as a 64-bit floating point value.
+ The raw 64-bit encoding of the double is read from the stream as a big-endian int64.
+ If the stream is exhausted partway through reading the bytes, this will return zero.
+ @see OutputStream::writeDoubleBigEndian, readFloatBigEndian
+ */
+ virtual double readDoubleBigEndian();
+
+ /** Reads an encoded 32-bit number from the stream using a space-saving compressed format.
+ For small values, this is more space-efficient than using readInt() and OutputStream::writeInt()
+ The format used is: number of significant bytes + up to 4 bytes in little-endian order.
+ @see OutputStream::writeCompressedInt()
+ */
+ virtual int readCompressedInt();
+
+ //==============================================================================
+ /** Reads a UTF-8 string from the stream, up to the next linefeed or carriage return.
+
+ This will read up to the next "\n" or "\r\n" or end-of-stream.
+
+ After this call, the stream's position will be left pointing to the next character
+ following the line-feed, but the linefeeds aren't included in the string that
+ is returned.
+ */
+ virtual String readNextLine();
+
+ /** Reads a zero-terminated UTF-8 string from the stream.
+
+ This will read characters from the stream until it hits a null character
+ or end-of-stream.
+
+ @see OutputStream::writeString, readEntireStreamAsString
+ */
+ virtual String readString();
+
+ /** Tries to read the whole stream and turn it into a string.
+
+ This will read from the stream's current position until the end-of-stream.
+ It can read from UTF-8 data, or UTF-16 if it detects suitable header-bytes.
+ */
+ virtual String readEntireStreamAsString();
+
+ /** Reads from the stream and appends the data to a MemoryBlock.
+
+ @param destBlock the block to append the data onto
+ @param maxNumBytesToRead if this is a positive value, it sets a limit to the number
+ of bytes that will be read - if it's negative, data
+ will be read until the stream is exhausted.
+ @returns the number of bytes that were added to the memory block
+ */
+ virtual size_t readIntoMemoryBlock (MemoryBlock& destBlock,
+ ssize_t maxNumBytesToRead = -1);
+
+ //==============================================================================
+ /** Returns the offset of the next byte that will be read from the stream.
+ @see setPosition
+ */
+ virtual int64 getPosition() = 0;
+
+ /** Tries to move the current read position of the stream.
+
+ The position is an absolute number of bytes from the stream's start.
+
+ Some streams might not be able to do this, in which case they should do
+ nothing and return false. Others might be able to manage it by resetting
+ themselves and skipping to the correct position, although this is
+ obviously a bit slow.
+
+ @returns true if the stream manages to reposition itself correctly
+ @see getPosition
+ */
+ virtual bool setPosition (int64 newPosition) = 0;
+
+ /** Reads and discards a number of bytes from the stream.
+
+ Some input streams might implement this efficiently, but the base
+ class will just keep reading data until the requisite number of bytes
+ have been done.
+ */
+ virtual void skipNextBytes (int64 numBytesToSkip);
+
+
+protected:
+ //==============================================================================
+ InputStream() noexcept {}
+
+private:
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InputStream)
+};
+
+#endif // JUCE_INPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.cpp
new file mode 100644
index 0000000..82b2d14
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.cpp
@@ -0,0 +1,159 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+MemoryInputStream::MemoryInputStream (const void* const sourceData,
+ const size_t sourceDataSize,
+ const bool keepInternalCopy)
+ : data (sourceData),
+ dataSize (sourceDataSize),
+ position (0)
+{
+ if (keepInternalCopy)
+ createInternalCopy();
+}
+
+MemoryInputStream::MemoryInputStream (const MemoryBlock& sourceData,
+ const bool keepInternalCopy)
+ : data (sourceData.getData()),
+ dataSize (sourceData.getSize()),
+ position (0)
+{
+ if (keepInternalCopy)
+ createInternalCopy();
+}
+
+void MemoryInputStream::createInternalCopy()
+{
+ internalCopy.malloc (dataSize);
+ memcpy (internalCopy, data, dataSize);
+ data = internalCopy;
+}
+
+MemoryInputStream::~MemoryInputStream()
+{
+}
+
+int64 MemoryInputStream::getTotalLength()
+{
+ return (int64) dataSize;
+}
+
+int MemoryInputStream::read (void* const buffer, const int howMany)
+{
+ jassert (buffer != nullptr && howMany >= 0);
+
+ const int num = jmin (howMany, (int) (dataSize - position));
+ if (num <= 0)
+ return 0;
+
+ memcpy (buffer, addBytesToPointer (data, position), (size_t) num);
+ position += (unsigned int) num;
+ return num;
+}
+
+bool MemoryInputStream::isExhausted()
+{
+ return position >= dataSize;
+}
+
+bool MemoryInputStream::setPosition (const int64 pos)
+{
+ position = (size_t) jlimit ((int64) 0, (int64) dataSize, pos);
+ return true;
+}
+
+int64 MemoryInputStream::getPosition()
+{
+ return (int64) position;
+}
+
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class MemoryStreamTests : public UnitTest
+{
+public:
+ MemoryStreamTests() : UnitTest ("MemoryInputStream & MemoryOutputStream") {}
+
+ void runTest()
+ {
+ beginTest ("Basics");
+ Random r = getRandom();
+
+ int randomInt = r.nextInt();
+ int64 randomInt64 = r.nextInt64();
+ double randomDouble = r.nextDouble();
+ String randomString (createRandomWideCharString (r));
+
+ MemoryOutputStream mo;
+ mo.writeInt (randomInt);
+ mo.writeIntBigEndian (randomInt);
+ mo.writeCompressedInt (randomInt);
+ mo.writeString (randomString);
+ mo.writeInt64 (randomInt64);
+ mo.writeInt64BigEndian (randomInt64);
+ mo.writeDouble (randomDouble);
+ mo.writeDoubleBigEndian (randomDouble);
+
+ MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
+ expect (mi.readInt() == randomInt);
+ expect (mi.readIntBigEndian() == randomInt);
+ expect (mi.readCompressedInt() == randomInt);
+ expectEquals (mi.readString(), randomString);
+ expect (mi.readInt64() == randomInt64);
+ expect (mi.readInt64BigEndian() == randomInt64);
+ expect (mi.readDouble() == randomDouble);
+ expect (mi.readDoubleBigEndian() == randomDouble);
+ }
+
+ static String createRandomWideCharString (Random& r)
+ {
+ juce_wchar buffer [50] = { 0 };
+
+ for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
+ {
+ if (r.nextBool())
+ {
+ do
+ {
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
+ }
+ while (! CharPointer_UTF16::canRepresent (buffer[i]));
+ }
+ else
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
+ }
+
+ return CharPointer_UTF32 (buffer);
+ }
+};
+
+static MemoryStreamTests memoryInputStreamUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.h
new file mode 100644
index 0000000..013bc39
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryInputStream.h
@@ -0,0 +1,97 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MEMORYINPUTSTREAM_H_INCLUDED
+#define JUCE_MEMORYINPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Allows a block of data to be accessed as a stream.
+
+ This can either be used to refer to a shared block of memory, or can make its
+ own internal copy of the data when the MemoryInputStream is created.
+*/
+class JUCE_API MemoryInputStream : public InputStream
+{
+public:
+ //==============================================================================
+ /** Creates a MemoryInputStream.
+
+ @param sourceData the block of data to use as the stream's source
+ @param sourceDataSize the number of bytes in the source data block
+ @param keepInternalCopyOfData if false, the stream will just keep a pointer to
+ the source data, so this data shouldn't be changed
+ for the lifetime of the stream; if this parameter is
+ true, the stream will make its own copy of the
+ data and use that.
+ */
+ MemoryInputStream (const void* sourceData,
+ size_t sourceDataSize,
+ bool keepInternalCopyOfData);
+
+ /** Creates a MemoryInputStream.
+
+ @param data a block of data to use as the stream's source
+ @param keepInternalCopyOfData if false, the stream will just keep a reference to
+ the source data, so this data shouldn't be changed
+ for the lifetime of the stream; if this parameter is
+ true, the stream will make its own copy of the
+ data and use that.
+ */
+ MemoryInputStream (const MemoryBlock& data,
+ bool keepInternalCopyOfData);
+
+ /** Destructor. */
+ ~MemoryInputStream();
+
+ /** Returns a pointer to the source data block from which this stream is reading. */
+ const void* getData() const noexcept { return data; }
+
+ /** Returns the number of bytes of source data in the block from which this stream is reading. */
+ size_t getDataSize() const noexcept { return dataSize; }
+
+ //==============================================================================
+ int64 getPosition() override;
+ bool setPosition (int64 pos) override;
+ int64 getTotalLength() override;
+ bool isExhausted() override;
+ int read (void* destBuffer, int maxBytesToRead) override;
+
+private:
+ //==============================================================================
+ const void* data;
+ size_t dataSize, position;
+ HeapBlock<char> internalCopy;
+
+ void createInternalCopy();
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryInputStream)
+};
+
+#endif // JUCE_MEMORYINPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.cpp
new file mode 100644
index 0000000..835b2bd
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.cpp
@@ -0,0 +1,214 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
+ : blockToUse (&internalBlock), externalData (nullptr),
+ position (0), size (0), availableSize (0)
+{
+ internalBlock.setSize (initialSize, false);
+}
+
+MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
+ const bool appendToExistingBlockContent)
+ : blockToUse (&memoryBlockToWriteTo), externalData (nullptr),
+ position (0), size (0), availableSize (0)
+{
+ if (appendToExistingBlockContent)
+ position = size = memoryBlockToWriteTo.getSize();
+}
+
+MemoryOutputStream::MemoryOutputStream (void* destBuffer, size_t destBufferSize)
+ : blockToUse (nullptr), externalData (destBuffer),
+ position (0), size (0), availableSize (destBufferSize)
+{
+ jassert (externalData != nullptr); // This must be a valid pointer.
+}
+
+MemoryOutputStream::~MemoryOutputStream()
+{
+ trimExternalBlockSize();
+}
+
+void MemoryOutputStream::flush()
+{
+ trimExternalBlockSize();
+}
+
+void MemoryOutputStream::trimExternalBlockSize()
+{
+ if (blockToUse != &internalBlock && blockToUse != nullptr)
+ blockToUse->setSize (size, false);
+}
+
+void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
+{
+ if (blockToUse != nullptr)
+ blockToUse->ensureSize (bytesToPreallocate + 1);
+}
+
+void MemoryOutputStream::reset() noexcept
+{
+ position = 0;
+ size = 0;
+}
+
+char* MemoryOutputStream::prepareToWrite (size_t numBytes)
+{
+ jassert ((ssize_t) numBytes >= 0);
+ size_t storageNeeded = position + numBytes;
+
+ char* data;
+
+ if (blockToUse != nullptr)
+ {
+ if (storageNeeded >= blockToUse->getSize())
+ blockToUse->ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
+
+ data = static_cast <char*> (blockToUse->getData());
+ }
+ else
+ {
+ if (storageNeeded > availableSize)
+ return nullptr;
+
+ data = static_cast <char*> (externalData);
+ }
+
+ char* const writePointer = data + position;
+ position += numBytes;
+ size = jmax (size, position);
+ return writePointer;
+}
+
+bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
+{
+ jassert (buffer != nullptr);
+
+ if (howMany == 0)
+ return true;
+
+ if (char* dest = prepareToWrite (howMany))
+ {
+ memcpy (dest, buffer, howMany);
+ return true;
+ }
+
+ return false;
+}
+
+bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
+{
+ if (howMany == 0)
+ return true;
+
+ if (char* dest = prepareToWrite (howMany))
+ {
+ memset (dest, byte, howMany);
+ return true;
+ }
+
+ return false;
+}
+
+bool MemoryOutputStream::appendUTF8Char (juce_wchar c)
+{
+ if (char* dest = prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c)))
+ {
+ CharPointer_UTF8 (dest).write (c);
+ return true;
+ }
+
+ return false;
+}
+
+MemoryBlock MemoryOutputStream::getMemoryBlock() const
+{
+ return MemoryBlock (getData(), getDataSize());
+}
+
+const void* MemoryOutputStream::getData() const noexcept
+{
+ if (blockToUse == nullptr)
+ return externalData;
+
+ if (blockToUse->getSize() > size)
+ static_cast <char*> (blockToUse->getData()) [size] = 0;
+
+ return blockToUse->getData();
+}
+
+bool MemoryOutputStream::setPosition (int64 newPosition)
+{
+ if (newPosition <= (int64) size)
+ {
+ // ok to seek backwards
+ position = jlimit ((size_t) 0, size, (size_t) newPosition);
+ return true;
+ }
+
+ // can't move beyond the end of the stream..
+ return false;
+}
+
+int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)
+{
+ // before writing from an input, see if we can preallocate to make it more efficient..
+ int64 availableData = source.getTotalLength() - source.getPosition();
+
+ if (availableData > 0)
+ {
+ if (maxNumBytesToWrite > availableData)
+ maxNumBytesToWrite = availableData;
+
+ if (blockToUse != nullptr)
+ preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);
+ }
+
+ return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
+}
+
+String MemoryOutputStream::toUTF8() const
+{
+ const char* const d = static_cast <const char*> (getData());
+ return String (CharPointer_UTF8 (d), CharPointer_UTF8 (d + getDataSize()));
+}
+
+String MemoryOutputStream::toString() const
+{
+ return String::createStringFromData (getData(), (int) getDataSize());
+}
+
+OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead)
+{
+ const size_t dataSize = streamToRead.getDataSize();
+
+ if (dataSize > 0)
+ stream.write (streamToRead.getData(), dataSize);
+
+ return stream;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.h
new file mode 100644
index 0000000..2e764ef
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_MemoryOutputStream.h
@@ -0,0 +1,139 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_MEMORYOUTPUTSTREAM_H_INCLUDED
+#define JUCE_MEMORYOUTPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Writes data to an internal memory buffer, which grows as required.
+
+ The data that was written into the stream can then be accessed later as
+ a contiguous block of memory.
+*/
+class JUCE_API MemoryOutputStream : public OutputStream
+{
+public:
+ //==============================================================================
+ /** Creates an empty memory stream, ready to be written into.
+ @param initialSize the intial amount of capacity to allocate for writing into
+ */
+ MemoryOutputStream (size_t initialSize = 256);
+
+ /** Creates a memory stream for writing into into a pre-existing MemoryBlock object.
+
+ Note that the destination block will always be larger than the amount of data
+ that has been written to the stream, because the MemoryOutputStream keeps some
+ spare capactity at its end. To trim the block's size down to fit the actual
+ data, call flush(), or delete the MemoryOutputStream.
+
+ @param memoryBlockToWriteTo the block into which new data will be written.
+ @param appendToExistingBlockContent if this is true, the contents of the block will be
+ kept, and new data will be appended to it. If false,
+ the block will be cleared before use
+ */
+ MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
+ bool appendToExistingBlockContent);
+
+ /** Creates a MemoryOutputStream that will write into a user-supplied, fixed-size
+ block of memory.
+ When using this mode, the stream will write directly into this memory area until
+ it's full, at which point write operations will fail.
+ */
+ MemoryOutputStream (void* destBuffer, size_t destBufferSize);
+
+ /** Destructor.
+ This will free any data that was written to it.
+ */
+ ~MemoryOutputStream();
+
+ //==============================================================================
+ /** Returns a pointer to the data that has been written to the stream.
+ @see getDataSize
+ */
+ const void* getData() const noexcept;
+
+ /** Returns the number of bytes of data that have been written to the stream.
+ @see getData
+ */
+ size_t getDataSize() const noexcept { return size; }
+
+ /** Resets the stream, clearing any data that has been written to it so far. */
+ void reset() noexcept;
+
+ /** Increases the internal storage capacity to be able to contain at least the specified
+ amount of data without needing to be resized.
+ */
+ void preallocate (size_t bytesToPreallocate);
+
+ /** Appends the utf-8 bytes for a unicode character */
+ bool appendUTF8Char (juce_wchar character);
+
+ /** Returns a String created from the (UTF8) data that has been written to the stream. */
+ String toUTF8() const;
+
+ /** Attempts to detect the encoding of the data and convert it to a string.
+ @see String::createStringFromData
+ */
+ String toString() const;
+
+ /** Returns a copy of the stream's data as a memory block. */
+ MemoryBlock getMemoryBlock() const;
+
+ //==============================================================================
+ /** If the stream is writing to a user-supplied MemoryBlock, this will trim any excess
+ capacity off the block, so that its length matches the amount of actual data that
+ has been written so far.
+ */
+ void flush();
+
+ bool write (const void*, size_t) override;
+ int64 getPosition() override { return (int64) position; }
+ bool setPosition (int64) override;
+ int64 writeFromInputStream (InputStream&, int64 maxNumBytesToWrite) override;
+ bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override;
+
+private:
+ //==============================================================================
+ MemoryBlock* const blockToUse;
+ MemoryBlock internalBlock;
+ void* externalData;
+ size_t position, size, availableSize;
+
+ void trimExternalBlockSize();
+ char* prepareToWrite (size_t);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream)
+};
+
+/** Copies all the data that has been written to a MemoryOutputStream into another stream. */
+OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead);
+
+
+#endif // JUCE_MEMORYOUTPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.cpp
new file mode 100644
index 0000000..c67e3fb
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.cpp
@@ -0,0 +1,351 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#if JUCE_DEBUG
+
+struct DanglingStreamChecker
+{
+ DanglingStreamChecker() {}
+
+ ~DanglingStreamChecker()
+ {
+ /*
+ It's always a bad idea to leak any object, but if you're leaking output
+ streams, then there's a good chance that you're failing to flush a file
+ to disk properly, which could result in corrupted data and other similar
+ nastiness..
+ */
+ jassert (activeStreams.size() == 0);
+ }
+
+ Array<void*, CriticalSection> activeStreams;
+};
+
+static DanglingStreamChecker danglingStreamChecker;
+#endif
+
+//==============================================================================
+OutputStream::OutputStream()
+ : newLineString (NewLine::getDefault())
+{
+ #if JUCE_DEBUG
+ danglingStreamChecker.activeStreams.add (this);
+ #endif
+}
+
+OutputStream::~OutputStream()
+{
+ #if JUCE_DEBUG
+ danglingStreamChecker.activeStreams.removeFirstMatchingValue (this);
+ #endif
+}
+
+//==============================================================================
+bool OutputStream::writeBool (const bool b)
+{
+ return writeByte (b ? (char) 1
+ : (char) 0);
+}
+
+bool OutputStream::writeByte (char byte)
+{
+ return write (&byte, 1);
+}
+
+bool OutputStream::writeRepeatedByte (uint8 byte, size_t numTimesToRepeat)
+{
+ for (size_t i = 0; i < numTimesToRepeat; ++i)
+ if (! writeByte ((char) byte))
+ return false;
+
+ return true;
+}
+
+bool OutputStream::writeShort (short value)
+{
+ const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value);
+ return write (&v, 2);
+}
+
+bool OutputStream::writeShortBigEndian (short value)
+{
+ const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value);
+ return write (&v, 2);
+}
+
+bool OutputStream::writeInt (int value)
+{
+ const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value);
+ return write (&v, 4);
+}
+
+bool OutputStream::writeIntBigEndian (int value)
+{
+ const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value);
+ return write (&v, 4);
+}
+
+bool OutputStream::writeCompressedInt (int value)
+{
+ unsigned int un = (value < 0) ? (unsigned int) -value
+ : (unsigned int) value;
+
+ uint8 data[5];
+ int num = 0;
+
+ while (un > 0)
+ {
+ data[++num] = (uint8) un;
+ un >>= 8;
+ }
+
+ data[0] = (uint8) num;
+
+ if (value < 0)
+ data[0] |= 0x80;
+
+ return write (data, (size_t) num + 1);
+}
+
+bool OutputStream::writeInt64 (int64 value)
+{
+ const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value);
+ return write (&v, 8);
+}
+
+bool OutputStream::writeInt64BigEndian (int64 value)
+{
+ const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value);
+ return write (&v, 8);
+}
+
+bool OutputStream::writeFloat (float value)
+{
+ union { int asInt; float asFloat; } n;
+ n.asFloat = value;
+ return writeInt (n.asInt);
+}
+
+bool OutputStream::writeFloatBigEndian (float value)
+{
+ union { int asInt; float asFloat; } n;
+ n.asFloat = value;
+ return writeIntBigEndian (n.asInt);
+}
+
+bool OutputStream::writeDouble (double value)
+{
+ union { int64 asInt; double asDouble; } n;
+ n.asDouble = value;
+ return writeInt64 (n.asInt);
+}
+
+bool OutputStream::writeDoubleBigEndian (double value)
+{
+ union { int64 asInt; double asDouble; } n;
+ n.asDouble = value;
+ return writeInt64BigEndian (n.asInt);
+}
+
+bool OutputStream::writeString (const String& text)
+{
+ #if (JUCE_STRING_UTF_TYPE == 8)
+ return write (text.toRawUTF8(), text.getNumBytesAsUTF8() + 1);
+ #else
+ // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind
+ // if lots of large, persistent strings were to be written to streams).
+ const size_t numBytes = text.getNumBytesAsUTF8() + 1;
+ HeapBlock<char> temp (numBytes);
+ text.copyToUTF8 (temp, numBytes);
+ return write (temp, numBytes);
+ #endif
+}
+
+bool OutputStream::writeText (const String& text, const bool asUTF16,
+ const bool writeUTF16ByteOrderMark)
+{
+ if (asUTF16)
+ {
+ if (writeUTF16ByteOrderMark)
+ write ("\x0ff\x0fe", 2);
+
+ String::CharPointerType src (text.getCharPointer());
+ bool lastCharWasReturn = false;
+
+ for (;;)
+ {
+ const juce_wchar c = src.getAndAdvance();
+
+ if (c == 0)
+ break;
+
+ if (c == '\n' && ! lastCharWasReturn)
+ writeShort ((short) '\r');
+
+ lastCharWasReturn = (c == L'\r');
+
+ if (! writeShort ((short) c))
+ return false;
+ }
+ }
+ else
+ {
+ const char* src = text.toUTF8();
+ const char* t = src;
+
+ for (;;)
+ {
+ if (*t == '\n')
+ {
+ if (t > src)
+ if (! write (src, (size_t) (t - src)))
+ return false;
+
+ if (! write ("\r\n", 2))
+ return false;
+
+ src = t + 1;
+ }
+ else if (*t == '\r')
+ {
+ if (t[1] == '\n')
+ ++t;
+ }
+ else if (*t == 0)
+ {
+ if (t > src)
+ if (! write (src, (size_t) (t - src)))
+ return false;
+
+ break;
+ }
+
+ ++t;
+ }
+ }
+
+ return true;
+}
+
+int64 OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite)
+{
+ if (numBytesToWrite < 0)
+ numBytesToWrite = std::numeric_limits<int64>::max();
+
+ int64 numWritten = 0;
+
+ while (numBytesToWrite > 0)
+ {
+ char buffer [8192];
+ const int num = source.read (buffer, (int) jmin (numBytesToWrite, (int64) sizeof (buffer)));
+
+ if (num <= 0)
+ break;
+
+ write (buffer, (size_t) num);
+
+ numBytesToWrite -= num;
+ numWritten += num;
+ }
+
+ return numWritten;
+}
+
+//==============================================================================
+void OutputStream::setNewLineString (const String& newLineString_)
+{
+ newLineString = newLineString_;
+}
+
+//==============================================================================
+template <typename IntegerType>
+static void writeIntToStream (OutputStream& stream, IntegerType number)
+{
+ char buffer [NumberToStringConverters::charsNeededForInt];
+ char* end = buffer + numElementsInArray (buffer);
+ const char* start = NumberToStringConverters::numberToString (end, number);
+ stream.write (start, (size_t) (end - start - 1));
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number)
+{
+ writeIntToStream (stream, number);
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int64 number)
+{
+ writeIntToStream (stream, number);
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const double number)
+{
+ return stream << String (number);
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char character)
+{
+ stream.writeByte (character);
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char* const text)
+{
+ stream.write (text, strlen (text));
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& data)
+{
+ if (data.getSize() > 0)
+ stream.write (data.getData(), data.getSize());
+
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead)
+{
+ FileInputStream in (fileToRead);
+
+ if (in.openedOk())
+ return stream << in;
+
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, InputStream& streamToRead)
+{
+ stream.writeFromInputStream (streamToRead, -1);
+ return stream;
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&)
+{
+ return stream << stream.getNewLineString();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.h
new file mode 100644
index 0000000..102ab5a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_OutputStream.h
@@ -0,0 +1,278 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_OUTPUTSTREAM_H_INCLUDED
+#define JUCE_OUTPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ The base class for streams that write data to some kind of destination.
+
+ Input and output streams are used throughout the library - subclasses can override
+ some or all of the virtual functions to implement their behaviour.
+
+ @see InputStream, MemoryOutputStream, FileOutputStream
+*/
+class JUCE_API OutputStream
+{
+protected:
+ //==============================================================================
+ OutputStream();
+
+public:
+ /** Destructor.
+
+ Some subclasses might want to do things like call flush() during their
+ destructors.
+ */
+ virtual ~OutputStream();
+
+ //==============================================================================
+ /** If the stream is using a buffer, this will ensure it gets written
+ out to the destination. */
+ virtual void flush() = 0;
+
+ /** Tries to move the stream's output position.
+
+ Not all streams will be able to seek to a new position - this will return
+ false if it fails to work.
+
+ @see getPosition
+ */
+ virtual bool setPosition (int64 newPosition) = 0;
+
+ /** Returns the stream's current position.
+
+ @see setPosition
+ */
+ virtual int64 getPosition() = 0;
+
+ //==============================================================================
+ /** Writes a block of data to the stream.
+
+ When creating a subclass of OutputStream, this is the only write method
+ that needs to be overloaded - the base class has methods for writing other
+ types of data which use this to do the work.
+
+ @param dataToWrite the target buffer to receive the data. This must not be null.
+ @param numberOfBytes the number of bytes to write.
+ @returns false if the write operation fails for some reason
+ */
+ virtual bool write (const void* dataToWrite,
+ size_t numberOfBytes) = 0;
+
+ //==============================================================================
+ /** Writes a single byte to the stream.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readByte
+ */
+ virtual bool writeByte (char byte);
+
+ /** Writes a boolean to the stream as a single byte.
+ This is encoded as a binary byte (not as text) with a value of 1 or 0.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readBool
+ */
+ virtual bool writeBool (bool boolValue);
+
+ /** Writes a 16-bit integer to the stream in a little-endian byte order.
+ This will write two bytes to the stream: (value & 0xff), then (value >> 8).
+ @returns false if the write operation fails for some reason
+ @see InputStream::readShort
+ */
+ virtual bool writeShort (short value);
+
+ /** Writes a 16-bit integer to the stream in a big-endian byte order.
+ This will write two bytes to the stream: (value >> 8), then (value & 0xff).
+ @returns false if the write operation fails for some reason
+ @see InputStream::readShortBigEndian
+ */
+ virtual bool writeShortBigEndian (short value);
+
+ /** Writes a 32-bit integer to the stream in a little-endian byte order.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readInt
+ */
+ virtual bool writeInt (int value);
+
+ /** Writes a 32-bit integer to the stream in a big-endian byte order.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readIntBigEndian
+ */
+ virtual bool writeIntBigEndian (int value);
+
+ /** Writes a 64-bit integer to the stream in a little-endian byte order.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readInt64
+ */
+ virtual bool writeInt64 (int64 value);
+
+ /** Writes a 64-bit integer to the stream in a big-endian byte order.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readInt64BigEndian
+ */
+ virtual bool writeInt64BigEndian (int64 value);
+
+ /** Writes a 32-bit floating point value to the stream in a binary format.
+ The binary 32-bit encoding of the float is written as a little-endian int.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readFloat
+ */
+ virtual bool writeFloat (float value);
+
+ /** Writes a 32-bit floating point value to the stream in a binary format.
+ The binary 32-bit encoding of the float is written as a big-endian int.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readFloatBigEndian
+ */
+ virtual bool writeFloatBigEndian (float value);
+
+ /** Writes a 64-bit floating point value to the stream in a binary format.
+ The eight raw bytes of the double value are written out as a little-endian 64-bit int.
+ @returns false if the write operation fails for some reason
+ @see InputStream::readDouble
+ */
+ virtual bool writeDouble (double value);
+
+ /** Writes a 64-bit floating point value to the stream in a binary format.
+ The eight raw bytes of the double value are written out as a big-endian 64-bit int.
+ @see InputStream::readDoubleBigEndian
+ @returns false if the write operation fails for some reason
+ */
+ virtual bool writeDoubleBigEndian (double value);
+
+ /** Writes a byte to the output stream a given number of times.
+ @returns false if the write operation fails for some reason
+ */
+ virtual bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat);
+
+ /** Writes a condensed binary encoding of a 32-bit integer.
+
+ If you're storing a lot of integers which are unlikely to have very large values,
+ this can save a lot of space, because values under 0xff will only take up 2 bytes,
+ under 0xffff only 3 bytes, etc.
+
+ The format used is: number of significant bytes + up to 4 bytes in little-endian order.
+
+ @returns false if the write operation fails for some reason
+ @see InputStream::readCompressedInt
+ */
+ virtual bool writeCompressedInt (int value);
+
+ /** Stores a string in the stream in a binary format.
+
+ This isn't the method to use if you're trying to append text to the end of a
+ text-file! It's intended for storing a string so that it can be retrieved later
+ by InputStream::readString().
+
+ It writes the string to the stream as UTF8, including the null termination character.
+
+ For appending text to a file, instead use writeText, or operator<<
+
+ @returns false if the write operation fails for some reason
+ @see InputStream::readString, writeText, operator<<
+ */
+ virtual bool writeString (const String& text);
+
+ /** Writes a string of text to the stream.
+
+ It can either write the text as UTF-8 or UTF-16, and can also add the UTF-16 byte-order-mark
+ bytes (0xff, 0xfe) to indicate the endianness (these should only be used at the start
+ of a file).
+
+ The method also replaces '\\n' characters in the text with '\\r\\n'.
+ @returns false if the write operation fails for some reason
+ */
+ virtual bool writeText (const String& text,
+ bool asUTF16,
+ bool writeUTF16ByteOrderMark);
+
+ /** Reads data from an input stream and writes it to this stream.
+
+ @param source the stream to read from
+ @param maxNumBytesToWrite the number of bytes to read from the stream (if this is
+ less than zero, it will keep reading until the input
+ is exhausted)
+ @returns the number of bytes written
+ */
+ virtual int64 writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite);
+
+ //==============================================================================
+ /** Sets the string that will be written to the stream when the writeNewLine()
+ method is called.
+ By default this will be set the value of NewLine::getDefault().
+ */
+ void setNewLineString (const String& newLineString);
+
+ /** Returns the current new-line string that was set by setNewLineString(). */
+ const String& getNewLineString() const noexcept { return newLineString; }
+
+private:
+ //==============================================================================
+ String newLineString;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream)
+};
+
+//==============================================================================
+/** Writes a number to a stream as 8-bit characters in the default system encoding. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, int number);
+
+/** Writes a number to a stream as 8-bit characters in the default system encoding. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, int64 number);
+
+/** Writes a number to a stream as 8-bit characters in the default system encoding. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, double number);
+
+/** Writes a character to a stream. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, char character);
+
+/** Writes a null-terminated text string to a stream. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char* text);
+
+/** Writes a block of data from a MemoryBlock to a stream. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& data);
+
+/** Writes the contents of a file to a stream. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead);
+
+/** Writes the complete contents of an input stream to an output stream. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, InputStream& streamToRead);
+
+/** Writes a new-line to a stream.
+ You can use the predefined symbol 'newLine' to invoke this, e.g.
+ @code
+ myOutputStream << "Hello World" << newLine << newLine;
+ @endcode
+ @see OutputStream::setNewLineString
+*/
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&);
+
+
+#endif // JUCE_OUTPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.cpp
new file mode 100644
index 0000000..c998c79
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.cpp
@@ -0,0 +1,82 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+SubregionStream::SubregionStream (InputStream* const sourceStream,
+ const int64 start, const int64 length,
+ const bool deleteSourceWhenDestroyed)
+ : source (sourceStream, deleteSourceWhenDestroyed),
+ startPositionInSourceStream (start),
+ lengthOfSourceStream (length)
+{
+ SubregionStream::setPosition (0);
+}
+
+SubregionStream::~SubregionStream()
+{
+}
+
+int64 SubregionStream::getTotalLength()
+{
+ const int64 srcLen = source->getTotalLength() - startPositionInSourceStream;
+
+ return lengthOfSourceStream >= 0 ? jmin (lengthOfSourceStream, srcLen)
+ : srcLen;
+}
+
+int64 SubregionStream::getPosition()
+{
+ return source->getPosition() - startPositionInSourceStream;
+}
+
+bool SubregionStream::setPosition (int64 newPosition)
+{
+ return source->setPosition (jmax ((int64) 0, newPosition + startPositionInSourceStream));
+}
+
+int SubregionStream::read (void* destBuffer, int maxBytesToRead)
+{
+ jassert (destBuffer != nullptr && maxBytesToRead >= 0);
+
+ if (lengthOfSourceStream < 0)
+ return source->read (destBuffer, maxBytesToRead);
+
+ maxBytesToRead = (int) jmin ((int64) maxBytesToRead, lengthOfSourceStream - getPosition());
+
+ if (maxBytesToRead <= 0)
+ return 0;
+
+ return source->read (destBuffer, maxBytesToRead);
+}
+
+bool SubregionStream::isExhausted()
+{
+ if (lengthOfSourceStream >= 0 && getPosition() >= lengthOfSourceStream)
+ return true;
+
+ return source->isExhausted();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.h
new file mode 100644
index 0000000..d291a03
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/streams/juce_SubregionStream.h
@@ -0,0 +1,88 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SUBREGIONSTREAM_H_INCLUDED
+#define JUCE_SUBREGIONSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/** Wraps another input stream, and reads from a specific part of it.
+
+ This lets you take a subsection of a stream and present it as an entire
+ stream in its own right.
+*/
+class JUCE_API SubregionStream : public InputStream
+{
+public:
+ //==============================================================================
+ /** Creates a SubregionStream from an input source.
+
+ @param sourceStream the source stream to read from
+ @param startPositionInSourceStream this is the position in the source stream that
+ corresponds to position 0 in this stream
+ @param lengthOfSourceStream this specifies the maximum number of bytes
+ from the source stream that will be passed through
+ by this stream. When the position of this stream
+ exceeds lengthOfSourceStream, it will cause an end-of-stream.
+ If the length passed in here is greater than the length
+ of the source stream (as returned by getTotalLength()),
+ then the smaller value will be used.
+ Passing a negative value for this parameter means it
+ will keep reading until the source's end-of-stream.
+ @param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be
+ deleted by this object when it is itself deleted.
+ */
+ SubregionStream (InputStream* sourceStream,
+ int64 startPositionInSourceStream,
+ int64 lengthOfSourceStream,
+ bool deleteSourceWhenDestroyed);
+
+ /** Destructor.
+
+ This may also delete the source stream, if that option was chosen when the
+ buffered stream was created.
+ */
+ ~SubregionStream();
+
+
+ //==============================================================================
+ int64 getTotalLength() override;
+ int64 getPosition() override;
+ bool setPosition (int64 newPosition) override;
+ int read (void* destBuffer, int maxBytesToRead) override;
+ bool isExhausted() override;
+
+private:
+ //==============================================================================
+ OptionalScopedPointer<InputStream> source;
+ const int64 startPositionInSourceStream, lengthOfSourceStream;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SubregionStream)
+};
+
+#endif // JUCE_SUBREGIONSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_PlatformDefs.h b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_PlatformDefs.h
new file mode 100644
index 0000000..1271185
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_PlatformDefs.h
@@ -0,0 +1,388 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_PLATFORMDEFS_H_INCLUDED
+#define JUCE_PLATFORMDEFS_H_INCLUDED
+
+//==============================================================================
+/* This file defines miscellaneous macros for debugging, assertions, etc.
+*/
+
+//==============================================================================
+#ifdef JUCE_FORCE_DEBUG
+ #undef JUCE_DEBUG
+
+ #if JUCE_FORCE_DEBUG
+ #define JUCE_DEBUG 1
+ #endif
+#endif
+
+/** This macro defines the C calling convention used as the standard for Juce calls. */
+#if JUCE_MSVC
+ #define JUCE_CALLTYPE __stdcall
+ #define JUCE_CDECL __cdecl
+#else
+ #define JUCE_CALLTYPE
+ #define JUCE_CDECL
+#endif
+
+//==============================================================================
+// Debugging and assertion macros
+
+#if JUCE_LOG_ASSERTIONS || JUCE_DEBUG
+ #define juce_LogCurrentAssertion juce::logAssertion (__FILE__, __LINE__);
+#else
+ #define juce_LogCurrentAssertion
+#endif
+
+//==============================================================================
+#if JUCE_IOS || JUCE_LINUX || JUCE_ANDROID || JUCE_PPC
+ /** This will try to break into the debugger if the app is currently being debugged.
+ If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending
+ on the platform.
+ @see jassert()
+ */
+ #define juce_breakDebugger { ::kill (0, SIGTRAP); }
+#elif JUCE_USE_INTRINSICS
+ #ifndef __INTEL_COMPILER
+ #pragma intrinsic (__debugbreak)
+ #endif
+ #define juce_breakDebugger { __debugbreak(); }
+#elif JUCE_GCC || JUCE_MAC
+ #if JUCE_NO_INLINE_ASM
+ #define juce_breakDebugger { }
+ #else
+ #define juce_breakDebugger { asm ("int $3"); }
+ #endif
+#else
+ #define juce_breakDebugger { __asm int 3 }
+#endif
+
+#if JUCE_CLANG && defined (__has_feature) && ! defined (JUCE_ANALYZER_NORETURN)
+ #if __has_feature (attribute_analyzer_noreturn)
+ inline void __attribute__((analyzer_noreturn)) juce_assert_noreturn() {}
+ #define JUCE_ANALYZER_NORETURN juce_assert_noreturn();
+ #endif
+#endif
+
+#ifndef JUCE_ANALYZER_NORETURN
+ #define JUCE_ANALYZER_NORETURN
+#endif
+
+//==============================================================================
+#if JUCE_DEBUG || DOXYGEN
+ /** Writes a string to the standard error stream.
+ This is only compiled in a debug build.
+ @see Logger::outputDebugString
+ */
+ #define DBG(dbgtext) { juce::String tempDbgBuf; tempDbgBuf << dbgtext; juce::Logger::outputDebugString (tempDbgBuf); }
+
+ //==============================================================================
+ /** This will always cause an assertion failure.
+ It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled for your build).
+ @see jassert
+ */
+ #define jassertfalse { juce_LogCurrentAssertion; if (juce::juce_isRunningUnderDebugger()) juce_breakDebugger; JUCE_ANALYZER_NORETURN }
+
+ //==============================================================================
+ /** Platform-independent assertion macro.
+
+ This macro gets turned into a no-op when you're building with debugging turned off, so be
+ careful that the expression you pass to it doesn't perform any actions that are vital for the
+ correct behaviour of your program!
+ @see jassertfalse
+ */
+ #define jassert(expression) { if (! (expression)) jassertfalse; }
+
+#else
+ //==============================================================================
+ // If debugging is disabled, these dummy debug and assertion macros are used..
+
+ #define DBG(dbgtext)
+ #define jassertfalse { juce_LogCurrentAssertion }
+
+ #if JUCE_LOG_ASSERTIONS
+ #define jassert(expression) { if (! (expression)) jassertfalse; }
+ #else
+ #define jassert(a) {}
+ #endif
+
+#endif
+
+//==============================================================================
+#ifndef DOXYGEN
+namespace htio2
+{
+namespace juce
+{
+ template <bool b> struct JuceStaticAssert;
+ template <> struct JuceStaticAssert <true> { static void dummy() {} };
+}
+}
+#endif
+
+/** A compile-time assertion macro.
+ If the expression parameter is false, the macro will cause a compile error. (The actual error
+ message that the compiler generates may be completely bizarre and seem to have no relation to
+ the place where you put the static_assert though!)
+*/
+#define static_jassert(expression) juce::JuceStaticAssert<expression>::dummy();
+
+/** This is a shorthand macro for declaring stubs for a class's copy constructor and operator=.
+
+ For example, instead of
+ @code
+ class MyClass
+ {
+ etc..
+
+ private:
+ MyClass (const MyClass&);
+ MyClass& operator= (const MyClass&);
+ };@endcode
+
+ ..you can just write:
+
+ @code
+ class MyClass
+ {
+ etc..
+
+ private:
+ JUCE_DECLARE_NON_COPYABLE (MyClass)
+ };@endcode
+*/
+#define JUCE_DECLARE_NON_COPYABLE(className) \
+ className (const className&) JUCE_DELETED_FUNCTION;\
+ className& operator= (const className&) JUCE_DELETED_FUNCTION;
+
+/** This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and
+ JUCE_LEAK_DETECTOR macro for a class.
+*/
+#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className) \
+ JUCE_DECLARE_NON_COPYABLE(className) \
+ JUCE_LEAK_DETECTOR(className)
+
+/** This macro can be added to class definitions to disable the use of new/delete to
+ allocate the object on the heap, forcing it to only be used as a stack or member variable.
+*/
+#define JUCE_PREVENT_HEAP_ALLOCATION \
+ private: \
+ static void* operator new (size_t) JUCE_DELETED_FUNCTION; \
+ static void operator delete (void*) JUCE_DELETED_FUNCTION;
+
+
+//==============================================================================
+#if ! DOXYGEN
+ #define JUCE_JOIN_MACRO_HELPER(a, b) a ## b
+ #define JUCE_STRINGIFY_MACRO_HELPER(a) #a
+#endif
+
+/** A good old-fashioned C macro concatenation helper.
+ This combines two items (which may themselves be macros) into a single string,
+ avoiding the pitfalls of the ## macro operator.
+*/
+#define JUCE_JOIN_MACRO(item1, item2) JUCE_JOIN_MACRO_HELPER (item1, item2)
+
+/** A handy C macro for stringifying any symbol, rather than just a macro parameter.
+*/
+#define JUCE_STRINGIFY(item) JUCE_STRINGIFY_MACRO_HELPER (item)
+
+
+//==============================================================================
+#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
+
+ #define JUCE_TRY try
+
+ #define JUCE_CATCH_ALL catch (...) {}
+ #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse; }
+
+ #if ! JUCE_MODULE_AVAILABLE_juce_gui_basics
+ #define JUCE_CATCH_EXCEPTION JUCE_CATCH_ALL
+ #else
+ /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplicationBase
+ object so they can be logged by the application if it wants to.
+ */
+ #define JUCE_CATCH_EXCEPTION \
+ catch (const std::exception& e) \
+ { \
+ juce::JUCEApplicationBase::sendUnhandledException (&e, __FILE__, __LINE__); \
+ } \
+ catch (...) \
+ { \
+ juce::JUCEApplicationBase::sendUnhandledException (nullptr, __FILE__, __LINE__); \
+ }
+ #endif
+
+#else
+
+ #define JUCE_TRY
+ #define JUCE_CATCH_EXCEPTION
+ #define JUCE_CATCH_ALL
+ #define JUCE_CATCH_ALL_ASSERT
+
+#endif
+
+//==============================================================================
+#if JUCE_DEBUG || DOXYGEN
+ /** A platform-independent way of forcing an inline function.
+ Use the syntax: @code
+ forcedinline void myfunction (int x)
+ @endcode
+ */
+ #define forcedinline inline
+#else
+ #if JUCE_MSVC
+ #define forcedinline __forceinline
+ #else
+ #define forcedinline inline __attribute__((always_inline))
+ #endif
+#endif
+
+#if JUCE_MSVC || DOXYGEN
+ /** This can be placed before a stack or member variable declaration to tell the compiler
+ to align it to the specified number of bytes. */
+ #define JUCE_ALIGN(bytes) __declspec (align (bytes))
+#else
+ #define JUCE_ALIGN(bytes) __attribute__ ((aligned (bytes)))
+#endif
+
+//==============================================================================
+// Cross-compiler deprecation macros..
+#ifdef DOXYGEN
+ /** This macro can be used to wrap a function which has been deprecated. */
+ #define JUCE_DEPRECATED(functionDef)
+ #define JUCE_DEPRECATED_WITH_BODY(functionDef, body)
+#elif JUCE_MSVC && ! JUCE_NO_DEPRECATION_WARNINGS
+ #define JUCE_DEPRECATED(functionDef) __declspec(deprecated) functionDef
+ #define JUCE_DEPRECATED_WITH_BODY(functionDef, body) __declspec(deprecated) functionDef body
+#elif JUCE_GCC && ! JUCE_NO_DEPRECATION_WARNINGS
+ #define JUCE_DEPRECATED(functionDef) functionDef __attribute__ ((deprecated))
+ #define JUCE_DEPRECATED_WITH_BODY(functionDef, body) functionDef __attribute__ ((deprecated)) body
+#else
+ #define JUCE_DEPRECATED(functionDef) functionDef
+ #define JUCE_DEPRECATED_WITH_BODY(functionDef, body) functionDef body
+#endif
+
+//==============================================================================
+#if JUCE_ANDROID && ! DOXYGEN
+ #define JUCE_MODAL_LOOPS_PERMITTED 0
+#elif ! defined (JUCE_MODAL_LOOPS_PERMITTED)
+ /** Some operating environments don't provide a modal loop mechanism, so this flag can be
+ used to disable any functions that try to run a modal loop. */
+ #define JUCE_MODAL_LOOPS_PERMITTED 1
+#endif
+
+//==============================================================================
+#if JUCE_GCC
+ #define JUCE_PACKED __attribute__((packed))
+#elif ! DOXYGEN
+ #define JUCE_PACKED
+#endif
+
+//==============================================================================
+// Here, we'll check for C++11 compiler support, and if it's not available, define
+// a few workarounds, so that we can still use some of the newer language features.
+#if (__cplusplus >= 201103L || defined (__GXX_EXPERIMENTAL_CXX0X__)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
+ #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1
+ #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
+ #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
+
+ #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL)
+ #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1
+ #endif
+
+ #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_DELETED_FUNCTION)
+ #define JUCE_DELETED_FUNCTION = delete
+ #endif
+#endif
+
+#if JUCE_CLANG && defined (__has_feature)
+ #if __has_feature (cxx_nullptr)
+ #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
+ #endif
+
+ #if __has_feature (cxx_noexcept)
+ #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1
+ #endif
+
+ #if __has_feature (cxx_rvalue_references)
+ #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
+ #endif
+
+ #if __has_feature (cxx_deleted_functions)
+ #define JUCE_DELETED_FUNCTION = delete
+ #endif
+
+ #ifndef JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL
+ #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1
+ #endif
+
+ #ifndef JUCE_COMPILER_SUPPORTS_ARC
+ #define JUCE_COMPILER_SUPPORTS_ARC 1
+ #endif
+#endif
+
+#if defined (_MSC_VER) && _MSC_VER >= 1600
+ #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
+ #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
+#endif
+
+#if defined (_MSC_VER) && _MSC_VER >= 1700
+ #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1
+#endif
+
+#ifndef JUCE_DELETED_FUNCTION
+ #define JUCE_DELETED_FUNCTION
+#endif
+
+//==============================================================================
+// Declare some fake versions of nullptr and noexcept, for older compilers:
+#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NOEXCEPT)
+ #ifdef noexcept
+ #undef noexcept
+ #endif
+ #define noexcept throw()
+ #if defined (_MSC_VER) && _MSC_VER > 1600
+ #define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining)
+ #endif
+#endif
+
+#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NULLPTR)
+ #ifdef nullptr
+ #undef nullptr
+ #endif
+ #define nullptr (0)
+#endif
+
+#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL)
+ #undef override
+ #define override
+#endif
+
+#endif // JUCE_PLATFORMDEFS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_StandardHeader.h b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_StandardHeader.h
new file mode 100644
index 0000000..2f420e8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_StandardHeader.h
@@ -0,0 +1,157 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STANDARDHEADER_H_INCLUDED
+#define JUCE_STANDARDHEADER_H_INCLUDED
+
+//==============================================================================
+/** Current JUCE version number.
+
+ See also SystemStats::getJUCEVersion() for a string version.
+*/
+#define JUCE_MAJOR_VERSION 3
+#define JUCE_MINOR_VERSION 0
+#define JUCE_BUILDNUMBER 8
+
+/** Current Juce version number.
+
+ Bits 16 to 32 = major version.
+ Bits 8 to 16 = minor version.
+ Bits 0 to 8 = point release.
+
+ See also SystemStats::getJUCEVersion() for a string version.
+*/
+#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8) + JUCE_BUILDNUMBER)
+
+
+//==============================================================================
+#include "juce_PlatformDefs.h"
+
+//==============================================================================
+// Now we'll include some common OS headers..
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4514 4245 4100)
+#endif
+
+#include <cstdlib>
+#include <cstdarg>
+#include <climits>
+#include <limits>
+#include <cmath>
+#include <cwchar>
+#include <stdexcept>
+#include <typeinfo>
+#include <cstring>
+#include <cstdio>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+#if JUCE_USE_INTRINSICS
+ #include <intrin.h>
+#endif
+
+#if JUCE_MAC || JUCE_IOS
+ #include <libkern/OSAtomic.h>
+#endif
+
+#if JUCE_LINUX
+ #include <signal.h>
+
+ #if __INTEL_COMPILER
+ #if __ia64__
+ #include <ia64intrin.h>
+ #else
+ #include <ia32intrin.h>
+ #endif
+ #endif
+#endif
+
+#if JUCE_MSVC && JUCE_DEBUG
+ #include <crtdbg.h>
+#endif
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+#if JUCE_ANDROID
+ #include <sys/atomics.h>
+ #include <byteswap.h>
+#endif
+
+// undef symbols that are sometimes set by misguided 3rd-party headers..
+#undef check
+#undef TYPE_BOOL
+#undef max
+#undef min
+
+//==============================================================================
+// DLL building settings on Windows
+#if JUCE_MSVC
+ #ifdef JUCE_DLL_BUILD
+ #define JUCE_API __declspec (dllexport)
+ #pragma warning (disable: 4251)
+ #elif defined (JUCE_DLL)
+ #define JUCE_API __declspec (dllimport)
+ #pragma warning (disable: 4251)
+ #endif
+ #ifdef __INTEL_COMPILER
+ #pragma warning (disable: 1125) // (virtual override warning)
+ #endif
+#elif defined (JUCE_DLL) || defined (JUCE_DLL_BUILD)
+ #define JUCE_API __attribute__ ((visibility("default")))
+#endif
+
+//==============================================================================
+#ifndef JUCE_API
+ #define JUCE_API /**< This macro is added to all juce public class declarations. */
+#endif
+
+#if JUCE_MSVC && JUCE_DLL_BUILD
+ #define JUCE_PUBLIC_IN_DLL_BUILD(declaration) public: declaration; private:
+#else
+ #define JUCE_PUBLIC_IN_DLL_BUILD(declaration) declaration;
+#endif
+
+/** This macro is added to all juce public function declarations. */
+#define JUCE_PUBLIC_FUNCTION JUCE_API JUCE_CALLTYPE
+
+#if (! defined (JUCE_CATCH_DEPRECATED_CODE_MISUSE)) && JUCE_DEBUG && ! DOXYGEN
+ /** This turns on some non-essential bits of code that should prevent old code from compiling
+ in cases where method signatures have changed, etc.
+ */
+ #define JUCE_CATCH_DEPRECATED_CODE_MISUSE 1
+#endif
+
+#ifndef DOXYGEN
+ #define JUCE_NAMESPACE juce // This old macro is deprecated: you should just use the juce namespace directly.
+#endif
+
+#endif // JUCE_STANDARDHEADER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.cpp
new file mode 100644
index 0000000..365e94d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.cpp
@@ -0,0 +1,183 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+String SystemStats::getJUCEVersion()
+{
+ // Some basic tests, to keep an eye on things and make sure these types work ok
+ // on all platforms. Let me know if any of these assertions fail on your system!
+ static_jassert (sizeof (pointer_sized_int) == sizeof (void*));
+ static_jassert (sizeof (int8) == 1);
+ static_jassert (sizeof (uint8) == 1);
+ static_jassert (sizeof (int16) == 2);
+ static_jassert (sizeof (uint16) == 2);
+ static_jassert (sizeof (int32) == 4);
+ static_jassert (sizeof (uint32) == 4);
+ static_jassert (sizeof (int64) == 8);
+ static_jassert (sizeof (uint64) == 8);
+
+ return "JUCE v" JUCE_STRINGIFY(JUCE_MAJOR_VERSION)
+ "." JUCE_STRINGIFY(JUCE_MINOR_VERSION)
+ "." JUCE_STRINGIFY(JUCE_BUILDNUMBER);
+}
+
+#if JUCE_ANDROID && ! defined (JUCE_DISABLE_JUCE_VERSION_PRINTING)
+ #define JUCE_DISABLE_JUCE_VERSION_PRINTING 1
+#endif
+
+#if JUCE_DEBUG && ! JUCE_DISABLE_JUCE_VERSION_PRINTING
+ struct JuceVersionPrinter
+ {
+ JuceVersionPrinter()
+ {
+ DBG (SystemStats::getJUCEVersion());
+ }
+ };
+
+ static JuceVersionPrinter juceVersionPrinter;
+#endif
+
+
+//==============================================================================
+struct CPUInformation
+{
+ CPUInformation() noexcept
+ : numCpus (0), hasMMX (false), hasSSE (false),
+ hasSSE2 (false), hasSSE3 (false), has3DNow (false)
+ {
+ initialise();
+ }
+
+ void initialise() noexcept;
+
+ int numCpus;
+ bool hasMMX, hasSSE, hasSSE2, hasSSE3, has3DNow;
+};
+
+static const CPUInformation& getCPUInformation() noexcept
+{
+ static CPUInformation info;
+ return info;
+}
+
+int SystemStats::getNumCpus() noexcept { return getCPUInformation().numCpus; }
+bool SystemStats::hasMMX() noexcept { return getCPUInformation().hasMMX; }
+bool SystemStats::hasSSE() noexcept { return getCPUInformation().hasSSE; }
+bool SystemStats::hasSSE2() noexcept { return getCPUInformation().hasSSE2; }
+bool SystemStats::hasSSE3() noexcept { return getCPUInformation().hasSSE3; }
+bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; }
+
+
+//==============================================================================
+String SystemStats::getStackBacktrace()
+{
+ String result;
+
+ #if JUCE_ANDROID || JUCE_MINGW
+ jassertfalse; // sorry, not implemented yet!
+
+ #elif JUCE_WINDOWS
+ HANDLE process = GetCurrentProcess();
+ SymInitialize (process, nullptr, TRUE);
+
+ void* stack[128];
+ int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr);
+
+ HeapBlock<SYMBOL_INFO> symbol;
+ symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1);
+ symbol->MaxNameLen = 255;
+ symbol->SizeOfStruct = sizeof (SYMBOL_INFO);
+
+ for (int i = 0; i < frames; ++i)
+ {
+ DWORD64 displacement = 0;
+
+ if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
+ {
+ result << i << ": ";
+
+ IMAGEHLP_MODULE64 moduleInfo;
+ zerostruct (moduleInfo);
+ moduleInfo.SizeOfStruct = sizeof (moduleInfo);
+
+ if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
+ result << moduleInfo.ModuleName << ": ";
+
+ result << symbol->Name << " + 0x" << String::toHexString ((int64) displacement) << newLine;
+ }
+ }
+
+ #else
+ void* stack[128];
+ int frames = backtrace (stack, numElementsInArray (stack));
+ char** frameStrings = backtrace_symbols (stack, frames);
+
+ for (int i = 0; i < frames; ++i)
+ result << frameStrings[i] << newLine;
+
+ ::free (frameStrings);
+ #endif
+
+ return result;
+}
+
+//==============================================================================
+static SystemStats::CrashHandlerFunction globalCrashHandler = nullptr;
+
+#if JUCE_WINDOWS
+static LONG WINAPI handleCrash (LPEXCEPTION_POINTERS)
+{
+ globalCrashHandler();
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#else
+static void handleCrash (int)
+{
+ globalCrashHandler();
+ kill (getpid(), SIGKILL);
+}
+
+int juce_siginterrupt (int sig, int flag);
+#endif
+
+void SystemStats::setApplicationCrashHandler (CrashHandlerFunction handler)
+{
+ jassert (handler != nullptr); // This must be a valid function.
+ globalCrashHandler = handler;
+
+ #if JUCE_WINDOWS
+ SetUnhandledExceptionFilter (handleCrash);
+ #else
+ const int signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGSYS };
+
+ for (int i = 0; i < numElementsInArray (signals); ++i)
+ {
+ ::signal (signals[i], handleCrash);
+ juce_siginterrupt (signals[i], 1);
+ }
+ #endif
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.h b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.h
new file mode 100644
index 0000000..835e6e6
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_SystemStats.h
@@ -0,0 +1,195 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SYSTEMSTATS_H_INCLUDED
+#define JUCE_SYSTEMSTATS_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Contains methods for finding out about the current hardware and OS configuration.
+*/
+class JUCE_API SystemStats
+{
+public:
+ //==============================================================================
+ /** Returns the current version of JUCE,
+ See also the JUCE_VERSION, JUCE_MAJOR_VERSION and JUCE_MINOR_VERSION macros.
+ */
+ static String getJUCEVersion();
+
+ //==============================================================================
+ /** The set of possible results of the getOperatingSystemType() method. */
+ enum OperatingSystemType
+ {
+ UnknownOS = 0,
+
+ Linux = 0x2000,
+ Android = 0x3000,
+ iOS = 0x8000,
+
+ MacOSX_10_4 = 0x1004,
+ MacOSX_10_5 = 0x1005,
+ MacOSX_10_6 = 0x1006,
+ MacOSX_10_7 = 0x1007,
+ MacOSX_10_8 = 0x1008,
+ MacOSX_10_9 = 0x1009,
+
+ Win2000 = 0x4105,
+ WinXP = 0x4106,
+ WinVista = 0x4107,
+ Windows7 = 0x4108,
+ Windows8_0 = 0x4109,
+ Windows8_1 = 0x410a,
+
+ Windows = 0x4000, /**< To test whether any version of Windows is running,
+ you can use the expression ((getOperatingSystemType() & Windows) != 0). */
+ };
+
+ /** Returns the type of operating system we're running on.
+
+ @returns one of the values from the OperatingSystemType enum.
+ @see getOperatingSystemName
+ */
+ static OperatingSystemType getOperatingSystemType();
+
+ /** Returns the name of the type of operating system we're running on.
+
+ @returns a string describing the OS type.
+ @see getOperatingSystemType
+ */
+ static String getOperatingSystemName();
+
+ /** Returns true if the OS is 64-bit, or false for a 32-bit OS. */
+ static bool isOperatingSystem64Bit();
+
+ /** Returns an environment variable.
+ If the named value isn't set, this will return the defaultValue string instead.
+ */
+ static String getEnvironmentVariable (const String& name, const String& defaultValue);
+
+ //==============================================================================
+ /** Returns the current user's name, if available.
+ @see getFullUserName()
+ */
+ static String getLogonName();
+
+ /** Returns the current user's full name, if available.
+ On some OSes, this may just return the same value as getLogonName().
+ @see getLogonName()
+ */
+ static String getFullUserName();
+
+ /** Returns the host-name of the computer. */
+ static String getComputerName();
+
+ /** Returns the language of the user's locale.
+ The return value is a 2 or 3 letter language code (ISO 639-1 or ISO 639-2)
+ */
+ static String getUserLanguage();
+
+ /** Returns the region of the user's locale.
+ The return value is a 2 letter country code (ISO 3166-1 alpha-2).
+ */
+ static String getUserRegion();
+
+ /** Returns the user's display language.
+ The return value is a 2 or 3 letter language code (ISO 639-1 or ISO 639-2).
+ Note that depending on the OS and region, this may also be followed by a dash
+ and a sub-region code, e.g "en-GB"
+ */
+ static String getDisplayLanguage();
+
+ /** This will attempt to return some kind of string describing the device.
+ If no description is available, it'll just return an empty string. You may
+ want to use this for things like determining the type of phone/iPad, etc.
+ */
+ static String getDeviceDescription();
+
+ //==============================================================================
+ // CPU and memory information..
+
+ /** Returns the number of CPU cores. */
+ static int getNumCpus() noexcept;
+
+ /** Returns the approximate CPU speed.
+ @returns the speed in megahertz, e.g. 1500, 2500, 32000 (depending on
+ what year you're reading this...)
+ */
+ static int getCpuSpeedInMegaherz();
+
+ /** Returns a string to indicate the CPU vendor.
+ Might not be known on some systems.
+ */
+ static String getCpuVendor();
+
+ static bool hasMMX() noexcept; /**< Returns true if Intel MMX instructions are available. */
+ static bool hasSSE() noexcept; /**< Returns true if Intel SSE instructions are available. */
+ static bool hasSSE2() noexcept; /**< Returns true if Intel SSE2 instructions are available. */
+ static bool hasSSE3() noexcept; /**< Returns true if Intel SSE2 instructions are available. */
+ static bool has3DNow() noexcept; /**< Returns true if AMD 3DNOW instructions are available. */
+
+ //==============================================================================
+ /** Finds out how much RAM is in the machine.
+ @returns the approximate number of megabytes of memory, or zero if
+ something goes wrong when finding out.
+ */
+ static int getMemorySizeInMegabytes();
+
+ /** Returns the system page-size.
+ This is only used by programmers with beards.
+ */
+ static int getPageSize();
+
+ //==============================================================================
+ /** Returns a backtrace of the current call-stack.
+ The usefulness of the result will depend on the level of debug symbols
+ that are available in the executable.
+ */
+ static String getStackBacktrace();
+
+ /** A void() function type, used by setApplicationCrashHandler(). */
+ typedef void (*CrashHandlerFunction)();
+
+ /** Sets up a global callback function that will be called if the application
+ executes some kind of illegal instruction.
+
+ You may want to call getStackBacktrace() in your handler function, to find out
+ where the problem happened and log it, etc.
+ */
+ static void setApplicationCrashHandler (CrashHandlerFunction);
+
+private:
+ //==============================================================================
+ SystemStats();
+
+ JUCE_DECLARE_NON_COPYABLE (SystemStats)
+};
+
+
+#endif // JUCE_SYSTEMSTATS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_TargetPlatform.h b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_TargetPlatform.h
new file mode 100644
index 0000000..86adc38
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/system/juce_TargetPlatform.h
@@ -0,0 +1,201 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_TARGETPLATFORM_H_INCLUDED
+#define JUCE_TARGETPLATFORM_H_INCLUDED
+
+//==============================================================================
+/* This file figures out which platform is being built, and defines some macros
+ that the rest of the code can use for OS-specific compilation.
+
+ Macros that will be set here are:
+
+ - One of JUCE_WINDOWS, JUCE_MAC JUCE_LINUX, JUCE_IOS, JUCE_ANDROID, etc.
+ - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture.
+ - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN.
+ - Either JUCE_INTEL or JUCE_PPC
+ - Either JUCE_GCC or JUCE_MSVC
+*/
+
+//==============================================================================
+#if (defined (_WIN32) || defined (_WIN64))
+ #define JUCE_WIN32 1
+ #define JUCE_WINDOWS 1
+#elif defined (JUCE_ANDROID)
+ #undef JUCE_ANDROID
+ #define JUCE_ANDROID 1
+#elif defined (LINUX) || defined (__linux__)
+ #define JUCE_LINUX 1
+#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__)
+ #define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers)
+ #define Component CarbonDummyCompName
+ #include <CoreFoundation/CoreFoundation.h> // (needed to find out what platform we're using)
+ #undef Point
+ #undef Component
+
+ #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ #define JUCE_IPHONE 1
+ #define JUCE_IOS 1
+ #else
+ #define JUCE_MAC 1
+ #endif
+#elif defined (__FreeBSD__)
+ #define JUCE_BSD 1
+#else
+ #error "Unknown platform!"
+#endif
+
+//==============================================================================
+#if JUCE_WINDOWS
+ #ifdef _MSC_VER
+ #ifdef _WIN64
+ #define JUCE_64BIT 1
+ #else
+ #define JUCE_32BIT 1
+ #endif
+ #endif
+
+ #ifdef _DEBUG
+ #define JUCE_DEBUG 1
+ #endif
+
+ #ifdef __MINGW32__
+ #define JUCE_MINGW 1
+ #ifdef __MINGW64__
+ #define JUCE_64BIT 1
+ #else
+ #define JUCE_32BIT 1
+ #endif
+ #endif
+
+ /** If defined, this indicates that the processor is little-endian. */
+ #define JUCE_LITTLE_ENDIAN 1
+
+ #define JUCE_INTEL 1
+#endif
+
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS
+
+ #if defined (DEBUG) || defined (_DEBUG) || ! (defined (NDEBUG) || defined (_NDEBUG))
+ #define JUCE_DEBUG 1
+ #endif
+
+ #if ! (defined (DEBUG) || defined (_DEBUG) || defined (NDEBUG) || defined (_NDEBUG))
+ #warning "Neither NDEBUG or DEBUG has been defined - you should set one of these to make it clear whether this is a release build,"
+ #endif
+
+ #ifdef __LITTLE_ENDIAN__
+ #define JUCE_LITTLE_ENDIAN 1
+ #else
+ #define JUCE_BIG_ENDIAN 1
+ #endif
+
+ #ifdef __LP64__
+ #define JUCE_64BIT 1
+ #else
+ #define JUCE_32BIT 1
+ #endif
+
+ #if defined (__ppc__) || defined (__ppc64__)
+ #define JUCE_PPC 1
+ #elif defined (__arm__) || defined (__arm64__)
+ #define JUCE_ARM 1
+ #else
+ #define JUCE_INTEL 1
+ #endif
+
+ #if JUCE_MAC && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
+ #error "Building for OSX 10.3 is no longer supported!"
+ #endif
+
+ #if JUCE_MAC && ! defined (MAC_OS_X_VERSION_10_5)
+ #error "To build with 10.4 compatibility, use a 10.5 or 10.6 SDK and set the deployment target to 10.4"
+ #endif
+#endif
+
+//==============================================================================
+#if JUCE_LINUX || JUCE_ANDROID
+
+ #ifdef _DEBUG
+ #define JUCE_DEBUG 1
+ #endif
+
+ // Allow override for big-endian Linux platforms
+ #if defined (__LITTLE_ENDIAN__) || ! defined (JUCE_BIG_ENDIAN)
+ #define JUCE_LITTLE_ENDIAN 1
+ #undef JUCE_BIG_ENDIAN
+ #else
+ #undef JUCE_LITTLE_ENDIAN
+ #define JUCE_BIG_ENDIAN 1
+ #endif
+
+ #if defined (__LP64__) || defined (_LP64)
+ #define JUCE_64BIT 1
+ #else
+ #define JUCE_32BIT 1
+ #endif
+
+ #if defined (__arm__) || defined (__arm64__)
+ #define JUCE_ARM 1
+ #elif __MMX__ || __SSE__ || __amd64__
+ #define JUCE_INTEL 1
+ #endif
+#endif
+
+//==============================================================================
+// Compiler type macros.
+
+#ifdef __clang__
+ #define JUCE_CLANG 1
+ #define JUCE_GCC 1
+#elif defined (__GNUC__)
+ #define JUCE_GCC 1
+#elif defined (_MSC_VER)
+ #define JUCE_MSVC 1
+
+ #if _MSC_VER < 1500
+ #define JUCE_VC8_OR_EARLIER 1
+
+ #if _MSC_VER < 1400
+ #define JUCE_VC7_OR_EARLIER 1
+
+ #if _MSC_VER < 1300
+ #warning "MSVC 6.0 is no longer supported!"
+ #endif
+ #endif
+ #endif
+
+ #if JUCE_64BIT || ! JUCE_VC7_OR_EARLIER
+ #define JUCE_USE_INTRINSICS 1
+ #endif
+#else
+ #error unknown compiler
+#endif
+
+#endif // JUCE_TARGETPLATFORM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_ASCII.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_ASCII.h
new file mode 100644
index 0000000..a966543
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_ASCII.h
@@ -0,0 +1,387 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHARPOINTER_ASCII_H_INCLUDED
+#define JUCE_CHARPOINTER_ASCII_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Wraps a pointer to a null-terminated ASCII character string, and provides
+ various methods to operate on the data.
+
+ A valid ASCII string is assumed to not contain any characters above 127.
+
+ @see CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32
+*/
+class CharPointer_ASCII
+{
+public:
+ typedef char CharType;
+
+ inline explicit CharPointer_ASCII (const CharType* const rawPointer) noexcept
+ : data (const_cast <CharType*> (rawPointer))
+ {
+ }
+
+ inline CharPointer_ASCII (const CharPointer_ASCII& other) noexcept
+ : data (other.data)
+ {
+ }
+
+ inline CharPointer_ASCII operator= (const CharPointer_ASCII other) noexcept
+ {
+ data = other.data;
+ return *this;
+ }
+
+ inline CharPointer_ASCII operator= (const CharType* text) noexcept
+ {
+ data = const_cast <CharType*> (text);
+ return *this;
+ }
+
+ /** This is a pointer comparison, it doesn't compare the actual text. */
+ inline bool operator== (CharPointer_ASCII other) const noexcept { return data == other.data; }
+ inline bool operator!= (CharPointer_ASCII other) const noexcept { return data != other.data; }
+ inline bool operator<= (CharPointer_ASCII other) const noexcept { return data <= other.data; }
+ inline bool operator< (CharPointer_ASCII other) const noexcept { return data < other.data; }
+ inline bool operator>= (CharPointer_ASCII other) const noexcept { return data >= other.data; }
+ inline bool operator> (CharPointer_ASCII other) const noexcept { return data > other.data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline CharType* getAddress() const noexcept { return data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline operator const CharType*() const noexcept { return data; }
+
+ /** Returns true if this pointer is pointing to a null character. */
+ inline bool isEmpty() const noexcept { return *data == 0; }
+
+ /** Returns the unicode character that this pointer is pointing to. */
+ inline juce_wchar operator*() const noexcept { return (juce_wchar) (uint8) *data; }
+
+ /** Moves this pointer along to the next character in the string. */
+ inline CharPointer_ASCII operator++() noexcept
+ {
+ ++data;
+ return *this;
+ }
+
+ /** Moves this pointer to the previous character in the string. */
+ inline CharPointer_ASCII operator--() noexcept
+ {
+ --data;
+ return *this;
+ }
+
+ /** Returns the character that this pointer is currently pointing to, and then
+ advances the pointer to point to the next character. */
+ inline juce_wchar getAndAdvance() noexcept { return (juce_wchar) (uint8) *data++; }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_ASCII operator++ (int) noexcept
+ {
+ CharPointer_ASCII temp (*this);
+ ++data;
+ return temp;
+ }
+
+ /** Moves this pointer forwards by the specified number of characters. */
+ inline void operator+= (const int numToSkip) noexcept
+ {
+ data += numToSkip;
+ }
+
+ inline void operator-= (const int numToSkip) noexcept
+ {
+ data -= numToSkip;
+ }
+
+ /** Returns the character at a given character index from the start of the string. */
+ inline juce_wchar operator[] (const int characterIndex) const noexcept
+ {
+ return (juce_wchar) (unsigned char) data [characterIndex];
+ }
+
+ /** Returns a pointer which is moved forwards from this one by the specified number of characters. */
+ CharPointer_ASCII operator+ (const int numToSkip) const noexcept
+ {
+ return CharPointer_ASCII (data + numToSkip);
+ }
+
+ /** Returns a pointer which is moved backwards from this one by the specified number of characters. */
+ CharPointer_ASCII operator- (const int numToSkip) const noexcept
+ {
+ return CharPointer_ASCII (data - numToSkip);
+ }
+
+ /** Writes a unicode character to this string, and advances this pointer to point to the next position. */
+ inline void write (const juce_wchar charToWrite) noexcept
+ {
+ *data++ = (char) charToWrite;
+ }
+
+ inline void replaceChar (const juce_wchar newChar) noexcept
+ {
+ *data = (char) newChar;
+ }
+
+ /** Writes a null character to this string (leaving the pointer's position unchanged). */
+ inline void writeNull() const noexcept
+ {
+ *data = 0;
+ }
+
+ /** Returns the number of characters in this string. */
+ size_t length() const noexcept
+ {
+ return (size_t) strlen (data);
+ }
+
+ /** Returns the number of characters in this string, or the given value, whichever is lower. */
+ size_t lengthUpTo (const size_t maxCharsToCount) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, maxCharsToCount);
+ }
+
+ /** Returns the number of characters in this string, or up to the given end pointer, whichever is lower. */
+ size_t lengthUpTo (const CharPointer_ASCII end) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, end);
+ }
+
+ /** Returns the number of bytes that are used to represent this string.
+ This includes the terminating null character.
+ */
+ size_t sizeInBytes() const noexcept
+ {
+ return length() + 1;
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ unicode character in this encoding format.
+ */
+ static inline size_t getBytesRequiredFor (const juce_wchar) noexcept
+ {
+ return 1;
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ string in this encoding format.
+ The value returned does NOT include the terminating null character.
+ */
+ template <class CharPointer>
+ static size_t getBytesRequiredFor (const CharPointer text) noexcept
+ {
+ return text.length();
+ }
+
+ /** Returns a pointer to the null character that terminates this string. */
+ CharPointer_ASCII findTerminatingNull() const noexcept
+ {
+ return CharPointer_ASCII (data + length());
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ template <typename CharPointer>
+ void writeAll (const CharPointer src) noexcept
+ {
+ CharacterFunctions::copyAll (*this, src);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ void writeAll (const CharPointer_ASCII src) noexcept
+ {
+ strcpy (data, src.data);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxDestBytes parameter specifies the maximum number of bytes that can be written
+ to the destination buffer before stopping.
+ */
+ template <typename CharPointer>
+ size_t writeWithDestByteLimit (const CharPointer src, const size_t maxDestBytes) noexcept
+ {
+ return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxChars parameter specifies the maximum number of characters that can be
+ written to the destination buffer before stopping (including the terminating null).
+ */
+ template <typename CharPointer>
+ void writeWithCharLimit (const CharPointer src, const int maxChars) noexcept
+ {
+ CharacterFunctions::copyWithCharLimit (*this, src, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compare (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compare (*this, other);
+ }
+
+ /** Compares this string with another one. */
+ int compare (const CharPointer_ASCII other) const noexcept
+ {
+ return strcmp (data, other.data);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareUpTo (*this, other, maxChars);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ int compareUpTo (const CharPointer_ASCII other, const int maxChars) const noexcept
+ {
+ return strncmp (data, other.data, (size_t) maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compareIgnoreCase (const CharPointer other) const
+ {
+ return CharacterFunctions::compareIgnoreCase (*this, other);
+ }
+
+ int compareIgnoreCase (const CharPointer_ASCII other) const
+ {
+ #if JUCE_WINDOWS
+ return stricmp (data, other.data);
+ #else
+ return strcasecmp (data, other.data);
+ #endif
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareIgnoreCaseUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars);
+ }
+
+ /** Returns the character index of a substring, or -1 if it isn't found. */
+ template <typename CharPointer>
+ int indexOf (const CharPointer stringToFind) const noexcept
+ {
+ return CharacterFunctions::indexOf (*this, stringToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind) const noexcept
+ {
+ int i = 0;
+
+ while (data[i] != 0)
+ {
+ if (data[i] == (char) charToFind)
+ return i;
+
+ ++i;
+ }
+
+ return -1;
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind, const bool ignoreCase) const noexcept
+ {
+ return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind)
+ : CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns true if the first character of this string is whitespace. */
+ bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; }
+ /** Returns true if the first character of this string is a digit. */
+ bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; }
+ /** Returns true if the first character of this string is a letter. */
+ bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; }
+ /** Returns true if the first character of this string is a letter or digit. */
+ bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; }
+ /** Returns true if the first character of this string is upper-case. */
+ bool isUpperCase() const { return CharacterFunctions::isUpperCase ((juce_wchar) (uint8) *data) != 0; }
+ /** Returns true if the first character of this string is lower-case. */
+ bool isLowerCase() const { return CharacterFunctions::isLowerCase ((juce_wchar) (uint8) *data) != 0; }
+
+ /** Returns an upper-case version of the first character of this string. */
+ juce_wchar toUpperCase() const noexcept { return CharacterFunctions::toUpperCase ((juce_wchar) (uint8) *data); }
+ /** Returns a lower-case version of the first character of this string. */
+ juce_wchar toLowerCase() const noexcept { return CharacterFunctions::toLowerCase ((juce_wchar) (uint8) *data); }
+
+ /** Parses this string as a 32-bit integer. */
+ int getIntValue32() const noexcept { return atoi (data); }
+
+ /** Parses this string as a 64-bit integer. */
+ int64 getIntValue64() const noexcept
+ {
+ #if JUCE_LINUX || JUCE_ANDROID
+ return atoll (data);
+ #elif JUCE_WINDOWS
+ return _atoi64 (data);
+ #else
+ return CharacterFunctions::getIntValue <int64, CharPointer_ASCII> (*this);
+ #endif
+ }
+
+ /** Parses this string as a floating point double. */
+ double getDoubleValue() const noexcept { return CharacterFunctions::getDoubleValue (*this); }
+
+ /** Returns the first non-whitespace character in the string. */
+ CharPointer_ASCII findEndOfWhitespace() const noexcept { return CharacterFunctions::findEndOfWhitespace (*this); }
+
+ /** Returns true if the given unicode character can be represented in this encoding. */
+ static bool canRepresent (juce_wchar character) noexcept
+ {
+ return ((unsigned int) character) < (unsigned int) 128;
+ }
+
+ /** Returns true if this data contains a valid string in this encoding. */
+ static bool isValidString (const CharType* dataToTest, int maxBytesToRead)
+ {
+ while (--maxBytesToRead >= 0)
+ {
+ if (((signed char) *dataToTest) <= 0)
+ return *dataToTest == 0;
+
+ ++dataToTest;
+ }
+
+ return true;
+ }
+
+private:
+ CharType* data;
+};
+
+
+#endif // JUCE_CHARPOINTER_ASCII_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF16.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF16.h
new file mode 100644
index 0000000..d0eba5c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF16.h
@@ -0,0 +1,525 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHARPOINTER_UTF16_H_INCLUDED
+#define JUCE_CHARPOINTER_UTF16_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Wraps a pointer to a null-terminated UTF-16 character string, and provides
+ various methods to operate on the data.
+ @see CharPointer_UTF8, CharPointer_UTF32
+*/
+class CharPointer_UTF16
+{
+public:
+ #if JUCE_NATIVE_WCHAR_IS_UTF16
+ typedef wchar_t CharType;
+ #else
+ typedef int16 CharType;
+ #endif
+
+ inline explicit CharPointer_UTF16 (const CharType* const rawPointer) noexcept
+ : data (const_cast <CharType*> (rawPointer))
+ {
+ }
+
+ inline CharPointer_UTF16 (const CharPointer_UTF16& other) noexcept
+ : data (other.data)
+ {
+ }
+
+ inline CharPointer_UTF16 operator= (CharPointer_UTF16 other) noexcept
+ {
+ data = other.data;
+ return *this;
+ }
+
+ inline CharPointer_UTF16 operator= (const CharType* text) noexcept
+ {
+ data = const_cast <CharType*> (text);
+ return *this;
+ }
+
+ /** This is a pointer comparison, it doesn't compare the actual text. */
+ inline bool operator== (CharPointer_UTF16 other) const noexcept { return data == other.data; }
+ inline bool operator!= (CharPointer_UTF16 other) const noexcept { return data != other.data; }
+ inline bool operator<= (CharPointer_UTF16 other) const noexcept { return data <= other.data; }
+ inline bool operator< (CharPointer_UTF16 other) const noexcept { return data < other.data; }
+ inline bool operator>= (CharPointer_UTF16 other) const noexcept { return data >= other.data; }
+ inline bool operator> (CharPointer_UTF16 other) const noexcept { return data > other.data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline CharType* getAddress() const noexcept { return data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline operator const CharType*() const noexcept { return data; }
+
+ /** Returns true if this pointer is pointing to a null character. */
+ inline bool isEmpty() const noexcept { return *data == 0; }
+
+ /** Returns the unicode character that this pointer is pointing to. */
+ juce_wchar operator*() const noexcept
+ {
+ uint32 n = (uint32) (uint16) *data;
+
+ if (n >= 0xd800 && n <= 0xdfff && ((uint32) (uint16) data[1]) >= 0xdc00)
+ n = 0x10000 + (((n - 0xd800) << 10) | (((uint32) (uint16) data[1]) - 0xdc00));
+
+ return (juce_wchar) n;
+ }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_UTF16 operator++() noexcept
+ {
+ const juce_wchar n = *data++;
+
+ if (n >= 0xd800 && n <= 0xdfff && ((uint32) (uint16) *data) >= 0xdc00)
+ ++data;
+
+ return *this;
+ }
+
+ /** Moves this pointer back to the previous character in the string. */
+ CharPointer_UTF16 operator--() noexcept
+ {
+ const juce_wchar n = *--data;
+
+ if (n >= 0xdc00 && n <= 0xdfff)
+ --data;
+
+ return *this;
+ }
+
+ /** Returns the character that this pointer is currently pointing to, and then
+ advances the pointer to point to the next character. */
+ juce_wchar getAndAdvance() noexcept
+ {
+ uint32 n = (uint32) (uint16) *data++;
+
+ if (n >= 0xd800 && n <= 0xdfff && ((uint32) (uint16) *data) >= 0xdc00)
+ n = 0x10000 + ((((n - 0xd800) << 10) | (((uint32) (uint16) *data++) - 0xdc00)));
+
+ return (juce_wchar) n;
+ }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_UTF16 operator++ (int) noexcept
+ {
+ CharPointer_UTF16 temp (*this);
+ ++*this;
+ return temp;
+ }
+
+ /** Moves this pointer forwards by the specified number of characters. */
+ void operator+= (int numToSkip) noexcept
+ {
+ if (numToSkip < 0)
+ {
+ while (++numToSkip <= 0)
+ --*this;
+ }
+ else
+ {
+ while (--numToSkip >= 0)
+ ++*this;
+ }
+ }
+
+ /** Moves this pointer backwards by the specified number of characters. */
+ void operator-= (int numToSkip) noexcept
+ {
+ operator+= (-numToSkip);
+ }
+
+ /** Returns the character at a given character index from the start of the string. */
+ juce_wchar operator[] (const int characterIndex) const noexcept
+ {
+ CharPointer_UTF16 p (*this);
+ p += characterIndex;
+ return *p;
+ }
+
+ /** Returns a pointer which is moved forwards from this one by the specified number of characters. */
+ CharPointer_UTF16 operator+ (const int numToSkip) const noexcept
+ {
+ CharPointer_UTF16 p (*this);
+ p += numToSkip;
+ return p;
+ }
+
+ /** Returns a pointer which is moved backwards from this one by the specified number of characters. */
+ CharPointer_UTF16 operator- (const int numToSkip) const noexcept
+ {
+ CharPointer_UTF16 p (*this);
+ p += -numToSkip;
+ return p;
+ }
+
+ /** Writes a unicode character to this string, and advances this pointer to point to the next position. */
+ void write (juce_wchar charToWrite) noexcept
+ {
+ if (charToWrite >= 0x10000)
+ {
+ charToWrite -= 0x10000;
+ *data++ = (CharType) (0xd800 + (charToWrite >> 10));
+ *data++ = (CharType) (0xdc00 + (charToWrite & 0x3ff));
+ }
+ else
+ {
+ *data++ = (CharType) charToWrite;
+ }
+ }
+
+ /** Writes a null character to this string (leaving the pointer's position unchanged). */
+ inline void writeNull() const noexcept
+ {
+ *data = 0;
+ }
+
+ /** Returns the number of characters in this string. */
+ size_t length() const noexcept
+ {
+ const CharType* d = data;
+ size_t count = 0;
+
+ for (;;)
+ {
+ const int n = *d++;
+
+ if (n >= 0xd800 && n <= 0xdfff)
+ {
+ if (*d++ == 0)
+ break;
+ }
+ else if (n == 0)
+ break;
+
+ ++count;
+ }
+
+ return count;
+ }
+
+ /** Returns the number of characters in this string, or the given value, whichever is lower. */
+ size_t lengthUpTo (const size_t maxCharsToCount) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, maxCharsToCount);
+ }
+
+ /** Returns the number of characters in this string, or up to the given end pointer, whichever is lower. */
+ size_t lengthUpTo (const CharPointer_UTF16 end) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, end);
+ }
+
+ /** Returns the number of bytes that are used to represent this string.
+ This includes the terminating null character.
+ */
+ size_t sizeInBytes() const noexcept
+ {
+ return sizeof (CharType) * (findNullIndex (data) + 1);
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ unicode character in this encoding format.
+ */
+ static size_t getBytesRequiredFor (const juce_wchar charToWrite) noexcept
+ {
+ return (charToWrite >= 0x10000) ? (sizeof (CharType) * 2) : sizeof (CharType);
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ string in this encoding format.
+ The value returned does NOT include the terminating null character.
+ */
+ template <class CharPointer>
+ static size_t getBytesRequiredFor (CharPointer text) noexcept
+ {
+ size_t count = 0;
+ juce_wchar n;
+
+ while ((n = text.getAndAdvance()) != 0)
+ count += getBytesRequiredFor (n);
+
+ return count;
+ }
+
+ /** Returns a pointer to the null character that terminates this string. */
+ CharPointer_UTF16 findTerminatingNull() const noexcept
+ {
+ const CharType* t = data;
+
+ while (*t != 0)
+ ++t;
+
+ return CharPointer_UTF16 (t);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ template <typename CharPointer>
+ void writeAll (const CharPointer src) noexcept
+ {
+ CharacterFunctions::copyAll (*this, src);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ void writeAll (const CharPointer_UTF16 src) noexcept
+ {
+ const CharType* s = src.data;
+
+ while ((*data = *s) != 0)
+ {
+ ++data;
+ ++s;
+ }
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxDestBytes parameter specifies the maximum number of bytes that can be written
+ to the destination buffer before stopping.
+ */
+ template <typename CharPointer>
+ size_t writeWithDestByteLimit (const CharPointer src, const size_t maxDestBytes) noexcept
+ {
+ return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxChars parameter specifies the maximum number of characters that can be
+ written to the destination buffer before stopping (including the terminating null).
+ */
+ template <typename CharPointer>
+ void writeWithCharLimit (const CharPointer src, const int maxChars) noexcept
+ {
+ CharacterFunctions::copyWithCharLimit (*this, src, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compare (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compare (*this, other);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareUpTo (*this, other, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compareIgnoreCase (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCase (*this, other);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareIgnoreCaseUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars);
+ }
+
+ #if JUCE_WINDOWS && ! DOXYGEN
+ int compareIgnoreCase (const CharPointer_UTF16 other) const noexcept
+ {
+ return _wcsicmp (data, other.data);
+ }
+
+ int compareIgnoreCaseUpTo (const CharPointer_UTF16 other, int maxChars) const noexcept
+ {
+ return _wcsnicmp (data, other.data, (size_t) maxChars);
+ }
+
+ int indexOf (const CharPointer_UTF16 stringToFind) const noexcept
+ {
+ const CharType* const t = wcsstr (data, stringToFind.getAddress());
+ return t == nullptr ? -1 : (int) (t - data);
+ }
+ #endif
+
+ /** Returns the character index of a substring, or -1 if it isn't found. */
+ template <typename CharPointer>
+ int indexOf (const CharPointer stringToFind) const noexcept
+ {
+ return CharacterFunctions::indexOf (*this, stringToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind) const noexcept
+ {
+ return CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind, const bool ignoreCase) const noexcept
+ {
+ return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind)
+ : CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns true if the first character of this string is whitespace. */
+ bool isWhitespace() const noexcept { return CharacterFunctions::isWhitespace (operator*()) != 0; }
+ /** Returns true if the first character of this string is a digit. */
+ bool isDigit() const noexcept { return CharacterFunctions::isDigit (operator*()) != 0; }
+ /** Returns true if the first character of this string is a letter. */
+ bool isLetter() const noexcept { return CharacterFunctions::isLetter (operator*()) != 0; }
+ /** Returns true if the first character of this string is a letter or digit. */
+ bool isLetterOrDigit() const noexcept { return CharacterFunctions::isLetterOrDigit (operator*()) != 0; }
+ /** Returns true if the first character of this string is upper-case. */
+ bool isUpperCase() const noexcept { return CharacterFunctions::isUpperCase (operator*()) != 0; }
+ /** Returns true if the first character of this string is lower-case. */
+ bool isLowerCase() const noexcept { return CharacterFunctions::isLowerCase (operator*()) != 0; }
+
+ /** Returns an upper-case version of the first character of this string. */
+ juce_wchar toUpperCase() const noexcept { return CharacterFunctions::toUpperCase (operator*()); }
+ /** Returns a lower-case version of the first character of this string. */
+ juce_wchar toLowerCase() const noexcept { return CharacterFunctions::toLowerCase (operator*()); }
+
+ /** Parses this string as a 32-bit integer. */
+ int getIntValue32() const noexcept
+ {
+ #if JUCE_WINDOWS
+ return _wtoi (data);
+ #else
+ return CharacterFunctions::getIntValue <int, CharPointer_UTF16> (*this);
+ #endif
+ }
+
+ /** Parses this string as a 64-bit integer. */
+ int64 getIntValue64() const noexcept
+ {
+ #if JUCE_WINDOWS
+ return _wtoi64 (data);
+ #else
+ return CharacterFunctions::getIntValue <int64, CharPointer_UTF16> (*this);
+ #endif
+ }
+
+ /** Parses this string as a floating point double. */
+ double getDoubleValue() const noexcept { return CharacterFunctions::getDoubleValue (*this); }
+
+ /** Returns the first non-whitespace character in the string. */
+ CharPointer_UTF16 findEndOfWhitespace() const noexcept { return CharacterFunctions::findEndOfWhitespace (*this); }
+
+ /** Returns true if the given unicode character can be represented in this encoding. */
+ static bool canRepresent (juce_wchar character) noexcept
+ {
+ return ((unsigned int) character) < (unsigned int) 0x10ffff
+ && (((unsigned int) character) < 0xd800 || ((unsigned int) character) > 0xdfff);
+ }
+
+ /** Returns true if this data contains a valid string in this encoding. */
+ static bool isValidString (const CharType* dataToTest, int maxBytesToRead)
+ {
+ maxBytesToRead /= (int) sizeof (CharType);
+
+ while (--maxBytesToRead >= 0 && *dataToTest != 0)
+ {
+ const uint32 n = (uint32) (uint16) *dataToTest++;
+
+ if (n >= 0xd800)
+ {
+ if (n > 0x10ffff)
+ return false;
+
+ if (n <= 0xdfff)
+ {
+ if (n > 0xdc00)
+ return false;
+
+ const uint32 nextChar = (uint32) (uint16) *dataToTest++;
+
+ if (nextChar < 0xdc00 || nextChar > 0xdfff)
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /** Atomically swaps this pointer for a new value, returning the previous value. */
+ CharPointer_UTF16 atomicSwap (const CharPointer_UTF16 newValue)
+ {
+ return CharPointer_UTF16 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data));
+ }
+
+ /** These values are the byte-order-mark (BOM) values for a UTF-16 stream. */
+ enum
+ {
+ byteOrderMarkBE1 = 0xfe,
+ byteOrderMarkBE2 = 0xff,
+ byteOrderMarkLE1 = 0xff,
+ byteOrderMarkLE2 = 0xfe
+ };
+
+ /** Returns true if the first pair of bytes in this pointer are the UTF16 byte-order mark (big endian).
+ The pointer must not be null, and must contain at least two valid bytes.
+ */
+ static bool isByteOrderMarkBigEndian (const void* possibleByteOrder) noexcept
+ {
+ jassert (possibleByteOrder != nullptr);
+ const uint8* const c = static_cast<const uint8*> (possibleByteOrder);
+
+ return c[0] == (uint8) byteOrderMarkBE1
+ && c[1] == (uint8) byteOrderMarkBE2;
+ }
+
+ /** Returns true if the first pair of bytes in this pointer are the UTF16 byte-order mark (little endian).
+ The pointer must not be null, and must contain at least two valid bytes.
+ */
+ static bool isByteOrderMarkLittleEndian (const void* possibleByteOrder) noexcept
+ {
+ jassert (possibleByteOrder != nullptr);
+ const uint8* const c = static_cast<const uint8*> (possibleByteOrder);
+
+ return c[0] == (uint8) byteOrderMarkLE1
+ && c[1] == (uint8) byteOrderMarkLE2;
+ }
+
+private:
+ CharType* data;
+
+ static unsigned int findNullIndex (const CharType* const t) noexcept
+ {
+ unsigned int n = 0;
+
+ while (t[n] != 0)
+ ++n;
+
+ return n;
+ }
+};
+
+
+#endif // JUCE_CHARPOINTER_UTF16_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF32.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF32.h
new file mode 100644
index 0000000..42cfe48
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF32.h
@@ -0,0 +1,378 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHARPOINTER_UTF32_H_INCLUDED
+#define JUCE_CHARPOINTER_UTF32_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Wraps a pointer to a null-terminated UTF-32 character string, and provides
+ various methods to operate on the data.
+ @see CharPointer_UTF8, CharPointer_UTF16
+*/
+class CharPointer_UTF32
+{
+public:
+ typedef juce_wchar CharType;
+
+ inline explicit CharPointer_UTF32 (const CharType* const rawPointer) noexcept
+ : data (const_cast <CharType*> (rawPointer))
+ {
+ }
+
+ inline CharPointer_UTF32 (const CharPointer_UTF32& other) noexcept
+ : data (other.data)
+ {
+ }
+
+ inline CharPointer_UTF32 operator= (CharPointer_UTF32 other) noexcept
+ {
+ data = other.data;
+ return *this;
+ }
+
+ inline CharPointer_UTF32 operator= (const CharType* text) noexcept
+ {
+ data = const_cast <CharType*> (text);
+ return *this;
+ }
+
+ /** This is a pointer comparison, it doesn't compare the actual text. */
+ inline bool operator== (CharPointer_UTF32 other) const noexcept { return data == other.data; }
+ inline bool operator!= (CharPointer_UTF32 other) const noexcept { return data != other.data; }
+ inline bool operator<= (CharPointer_UTF32 other) const noexcept { return data <= other.data; }
+ inline bool operator< (CharPointer_UTF32 other) const noexcept { return data < other.data; }
+ inline bool operator>= (CharPointer_UTF32 other) const noexcept { return data >= other.data; }
+ inline bool operator> (CharPointer_UTF32 other) const noexcept { return data > other.data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline CharType* getAddress() const noexcept { return data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline operator const CharType*() const noexcept { return data; }
+
+ /** Returns true if this pointer is pointing to a null character. */
+ inline bool isEmpty() const noexcept { return *data == 0; }
+
+ /** Returns the unicode character that this pointer is pointing to. */
+ inline juce_wchar operator*() const noexcept { return *data; }
+
+ /** Moves this pointer along to the next character in the string. */
+ inline CharPointer_UTF32 operator++() noexcept
+ {
+ ++data;
+ return *this;
+ }
+
+ /** Moves this pointer to the previous character in the string. */
+ inline CharPointer_UTF32 operator--() noexcept
+ {
+ --data;
+ return *this;
+ }
+
+ /** Returns the character that this pointer is currently pointing to, and then
+ advances the pointer to point to the next character. */
+ inline juce_wchar getAndAdvance() noexcept { return *data++; }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_UTF32 operator++ (int) noexcept
+ {
+ CharPointer_UTF32 temp (*this);
+ ++data;
+ return temp;
+ }
+
+ /** Moves this pointer forwards by the specified number of characters. */
+ inline void operator+= (const int numToSkip) noexcept
+ {
+ data += numToSkip;
+ }
+
+ inline void operator-= (const int numToSkip) noexcept
+ {
+ data -= numToSkip;
+ }
+
+ /** Returns the character at a given character index from the start of the string. */
+ inline juce_wchar& operator[] (const int characterIndex) const noexcept
+ {
+ return data [characterIndex];
+ }
+
+ /** Returns a pointer which is moved forwards from this one by the specified number of characters. */
+ CharPointer_UTF32 operator+ (const int numToSkip) const noexcept
+ {
+ return CharPointer_UTF32 (data + numToSkip);
+ }
+
+ /** Returns a pointer which is moved backwards from this one by the specified number of characters. */
+ CharPointer_UTF32 operator- (const int numToSkip) const noexcept
+ {
+ return CharPointer_UTF32 (data - numToSkip);
+ }
+
+ /** Writes a unicode character to this string, and advances this pointer to point to the next position. */
+ inline void write (const juce_wchar charToWrite) noexcept
+ {
+ *data++ = charToWrite;
+ }
+
+ inline void replaceChar (const juce_wchar newChar) noexcept
+ {
+ *data = newChar;
+ }
+
+ /** Writes a null character to this string (leaving the pointer's position unchanged). */
+ inline void writeNull() const noexcept
+ {
+ *data = 0;
+ }
+
+ /** Returns the number of characters in this string. */
+ size_t length() const noexcept
+ {
+ #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID
+ return wcslen (data);
+ #else
+ size_t n = 0;
+ while (data[n] != 0)
+ ++n;
+ return n;
+ #endif
+ }
+
+ /** Returns the number of characters in this string, or the given value, whichever is lower. */
+ size_t lengthUpTo (const size_t maxCharsToCount) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, maxCharsToCount);
+ }
+
+ /** Returns the number of characters in this string, or up to the given end pointer, whichever is lower. */
+ size_t lengthUpTo (const CharPointer_UTF32 end) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, end);
+ }
+
+ /** Returns the number of bytes that are used to represent this string.
+ This includes the terminating null character.
+ */
+ size_t sizeInBytes() const noexcept
+ {
+ return sizeof (CharType) * (length() + 1);
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ unicode character in this encoding format.
+ */
+ static inline size_t getBytesRequiredFor (const juce_wchar) noexcept
+ {
+ return sizeof (CharType);
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ string in this encoding format.
+ The value returned does NOT include the terminating null character.
+ */
+ template <class CharPointer>
+ static size_t getBytesRequiredFor (const CharPointer text) noexcept
+ {
+ return sizeof (CharType) * text.length();
+ }
+
+ /** Returns a pointer to the null character that terminates this string. */
+ CharPointer_UTF32 findTerminatingNull() const noexcept
+ {
+ return CharPointer_UTF32 (data + length());
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ template <typename CharPointer>
+ void writeAll (const CharPointer src) noexcept
+ {
+ CharacterFunctions::copyAll (*this, src);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ void writeAll (const CharPointer_UTF32 src) noexcept
+ {
+ const CharType* s = src.data;
+
+ while ((*data = *s) != 0)
+ {
+ ++data;
+ ++s;
+ }
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxDestBytes parameter specifies the maximum number of bytes that can be written
+ to the destination buffer before stopping.
+ */
+ template <typename CharPointer>
+ size_t writeWithDestByteLimit (const CharPointer src, const size_t maxDestBytes) noexcept
+ {
+ return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxChars parameter specifies the maximum number of characters that can be
+ written to the destination buffer before stopping (including the terminating null).
+ */
+ template <typename CharPointer>
+ void writeWithCharLimit (const CharPointer src, const int maxChars) noexcept
+ {
+ CharacterFunctions::copyWithCharLimit (*this, src, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compare (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compare (*this, other);
+ }
+
+ #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID
+ /** Compares this string with another one. */
+ int compare (const CharPointer_UTF32 other) const noexcept
+ {
+ return wcscmp (data, other.data);
+ }
+ #endif
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareUpTo (*this, other, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compareIgnoreCase (const CharPointer other) const
+ {
+ return CharacterFunctions::compareIgnoreCase (*this, other);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareIgnoreCaseUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars);
+ }
+
+ /** Returns the character index of a substring, or -1 if it isn't found. */
+ template <typename CharPointer>
+ int indexOf (const CharPointer stringToFind) const noexcept
+ {
+ return CharacterFunctions::indexOf (*this, stringToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind) const noexcept
+ {
+ int i = 0;
+
+ while (data[i] != 0)
+ {
+ if (data[i] == charToFind)
+ return i;
+
+ ++i;
+ }
+
+ return -1;
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind, const bool ignoreCase) const noexcept
+ {
+ return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind)
+ : CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns true if the first character of this string is whitespace. */
+ bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; }
+ /** Returns true if the first character of this string is a digit. */
+ bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; }
+ /** Returns true if the first character of this string is a letter. */
+ bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; }
+ /** Returns true if the first character of this string is a letter or digit. */
+ bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; }
+ /** Returns true if the first character of this string is upper-case. */
+ bool isUpperCase() const { return CharacterFunctions::isUpperCase (*data) != 0; }
+ /** Returns true if the first character of this string is lower-case. */
+ bool isLowerCase() const { return CharacterFunctions::isLowerCase (*data) != 0; }
+
+ /** Returns an upper-case version of the first character of this string. */
+ juce_wchar toUpperCase() const noexcept { return CharacterFunctions::toUpperCase (*data); }
+ /** Returns a lower-case version of the first character of this string. */
+ juce_wchar toLowerCase() const noexcept { return CharacterFunctions::toLowerCase (*data); }
+
+ /** Parses this string as a 32-bit integer. */
+ int getIntValue32() const noexcept { return CharacterFunctions::getIntValue <int, CharPointer_UTF32> (*this); }
+ /** Parses this string as a 64-bit integer. */
+ int64 getIntValue64() const noexcept { return CharacterFunctions::getIntValue <int64, CharPointer_UTF32> (*this); }
+
+ /** Parses this string as a floating point double. */
+ double getDoubleValue() const noexcept { return CharacterFunctions::getDoubleValue (*this); }
+
+ /** Returns the first non-whitespace character in the string. */
+ CharPointer_UTF32 findEndOfWhitespace() const noexcept { return CharacterFunctions::findEndOfWhitespace (*this); }
+
+ /** Returns true if the given unicode character can be represented in this encoding. */
+ static bool canRepresent (juce_wchar character) noexcept
+ {
+ return ((unsigned int) character) < (unsigned int) 0x10ffff;
+ }
+
+ /** Returns true if this data contains a valid string in this encoding. */
+ static bool isValidString (const CharType* dataToTest, int maxBytesToRead)
+ {
+ maxBytesToRead /= (int) sizeof (CharType);
+
+ while (--maxBytesToRead >= 0 && *dataToTest != 0)
+ if (! canRepresent (*dataToTest++))
+ return false;
+
+ return true;
+ }
+
+ /** Atomically swaps this pointer for a new value, returning the previous value. */
+ CharPointer_UTF32 atomicSwap (const CharPointer_UTF32 newValue)
+ {
+ return CharPointer_UTF32 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data));
+ }
+
+private:
+ CharType* data;
+};
+
+
+#endif // JUCE_CHARPOINTER_UTF32_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF8.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF8.h
new file mode 100644
index 0000000..78d9a97
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharPointer_UTF8.h
@@ -0,0 +1,572 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHARPOINTER_UTF8_H_INCLUDED
+#define JUCE_CHARPOINTER_UTF8_H_INCLUDED
+
+//==============================================================================
+/**
+ Wraps a pointer to a null-terminated UTF-8 character string, and provides
+ various methods to operate on the data.
+ @see CharPointer_UTF16, CharPointer_UTF32
+*/
+class CharPointer_UTF8
+{
+public:
+ typedef char CharType;
+
+ inline explicit CharPointer_UTF8 (const CharType* const rawPointer) noexcept
+ : data (const_cast <CharType*> (rawPointer))
+ {
+ }
+
+ inline CharPointer_UTF8 (const CharPointer_UTF8& other) noexcept
+ : data (other.data)
+ {
+ }
+
+ inline CharPointer_UTF8 operator= (CharPointer_UTF8 other) noexcept
+ {
+ data = other.data;
+ return *this;
+ }
+
+ inline CharPointer_UTF8 operator= (const CharType* text) noexcept
+ {
+ data = const_cast <CharType*> (text);
+ return *this;
+ }
+
+ /** This is a pointer comparison, it doesn't compare the actual text. */
+ inline bool operator== (CharPointer_UTF8 other) const noexcept { return data == other.data; }
+ inline bool operator!= (CharPointer_UTF8 other) const noexcept { return data != other.data; }
+ inline bool operator<= (CharPointer_UTF8 other) const noexcept { return data <= other.data; }
+ inline bool operator< (CharPointer_UTF8 other) const noexcept { return data < other.data; }
+ inline bool operator>= (CharPointer_UTF8 other) const noexcept { return data >= other.data; }
+ inline bool operator> (CharPointer_UTF8 other) const noexcept { return data > other.data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline CharType* getAddress() const noexcept { return data; }
+
+ /** Returns the address that this pointer is pointing to. */
+ inline operator const CharType*() const noexcept { return data; }
+
+ /** Returns true if this pointer is pointing to a null character. */
+ inline bool isEmpty() const noexcept { return *data == 0; }
+
+ /** Returns the unicode character that this pointer is pointing to. */
+ juce_wchar operator*() const noexcept
+ {
+ const signed char byte = (signed char) *data;
+
+ if (byte >= 0)
+ return (juce_wchar) (uint8) byte;
+
+ uint32 n = (uint32) (uint8) byte;
+ uint32 mask = 0x7f;
+ uint32 bit = 0x40;
+ size_t numExtraValues = 0;
+
+ while ((n & bit) != 0 && bit > 0x10)
+ {
+ mask >>= 1;
+ ++numExtraValues;
+ bit >>= 1;
+ }
+
+ n &= mask;
+
+ for (size_t i = 1; i <= numExtraValues; ++i)
+ {
+ const uint8 nextByte = (uint8) data [i];
+
+ if ((nextByte & 0xc0) != 0x80)
+ break;
+
+ n <<= 6;
+ n |= (nextByte & 0x3f);
+ }
+
+ return (juce_wchar) n;
+ }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_UTF8& operator++() noexcept
+ {
+ jassert (*data != 0); // trying to advance past the end of the string?
+ const signed char n = (signed char) *data++;
+
+ if (n < 0)
+ {
+ juce_wchar bit = 0x40;
+
+ while ((n & bit) != 0 && bit > 0x8)
+ {
+ ++data;
+ bit >>= 1;
+ }
+ }
+
+ return *this;
+ }
+
+ /** Moves this pointer back to the previous character in the string. */
+ CharPointer_UTF8 operator--() noexcept
+ {
+ int count = 0;
+
+ while ((*--data & 0xc0) == 0x80 && ++count < 4)
+ {}
+
+ return *this;
+ }
+
+ /** Returns the character that this pointer is currently pointing to, and then
+ advances the pointer to point to the next character. */
+ juce_wchar getAndAdvance() noexcept
+ {
+ const signed char byte = (signed char) *data++;
+
+ if (byte >= 0)
+ return (juce_wchar) (uint8) byte;
+
+ uint32 n = (uint32) (uint8) byte;
+ uint32 mask = 0x7f;
+ uint32 bit = 0x40;
+ int numExtraValues = 0;
+
+ while ((n & bit) != 0 && bit > 0x8)
+ {
+ mask >>= 1;
+ ++numExtraValues;
+ bit >>= 1;
+ }
+
+ n &= mask;
+
+ while (--numExtraValues >= 0)
+ {
+ const uint32 nextByte = (uint32) (uint8) *data;
+
+ if ((nextByte & 0xc0) != 0x80)
+ break;
+
+ ++data;
+ n <<= 6;
+ n |= (nextByte & 0x3f);
+ }
+
+ return (juce_wchar) n;
+ }
+
+ /** Moves this pointer along to the next character in the string. */
+ CharPointer_UTF8 operator++ (int) noexcept
+ {
+ CharPointer_UTF8 temp (*this);
+ ++*this;
+ return temp;
+ }
+
+ /** Moves this pointer forwards by the specified number of characters. */
+ void operator+= (int numToSkip) noexcept
+ {
+ if (numToSkip < 0)
+ {
+ while (++numToSkip <= 0)
+ --*this;
+ }
+ else
+ {
+ while (--numToSkip >= 0)
+ ++*this;
+ }
+ }
+
+ /** Moves this pointer backwards by the specified number of characters. */
+ void operator-= (int numToSkip) noexcept
+ {
+ operator+= (-numToSkip);
+ }
+
+ /** Returns the character at a given character index from the start of the string. */
+ juce_wchar operator[] (int characterIndex) const noexcept
+ {
+ CharPointer_UTF8 p (*this);
+ p += characterIndex;
+ return *p;
+ }
+
+ /** Returns a pointer which is moved forwards from this one by the specified number of characters. */
+ CharPointer_UTF8 operator+ (int numToSkip) const noexcept
+ {
+ CharPointer_UTF8 p (*this);
+ p += numToSkip;
+ return p;
+ }
+
+ /** Returns a pointer which is moved backwards from this one by the specified number of characters. */
+ CharPointer_UTF8 operator- (int numToSkip) const noexcept
+ {
+ CharPointer_UTF8 p (*this);
+ p += -numToSkip;
+ return p;
+ }
+
+ /** Returns the number of characters in this string. */
+ size_t length() const noexcept
+ {
+ const CharType* d = data;
+ size_t count = 0;
+
+ for (;;)
+ {
+ const uint32 n = (uint32) (uint8) *d++;
+
+ if ((n & 0x80) != 0)
+ {
+ while ((*d & 0xc0) == 0x80)
+ ++d;
+ }
+ else if (n == 0)
+ break;
+
+ ++count;
+ }
+
+ return count;
+ }
+
+ /** Returns the number of characters in this string, or the given value, whichever is lower. */
+ size_t lengthUpTo (const size_t maxCharsToCount) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, maxCharsToCount);
+ }
+
+ /** Returns the number of characters in this string, or up to the given end pointer, whichever is lower. */
+ size_t lengthUpTo (const CharPointer_UTF8 end) const noexcept
+ {
+ return CharacterFunctions::lengthUpTo (*this, end);
+ }
+
+ /** Returns the number of bytes that are used to represent this string.
+ This includes the terminating null character.
+ */
+ size_t sizeInBytes() const noexcept
+ {
+ jassert (data != nullptr);
+ return strlen (data) + 1;
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ unicode character in this encoding format.
+ */
+ static size_t getBytesRequiredFor (const juce_wchar charToWrite) noexcept
+ {
+ size_t num = 1;
+ const uint32 c = (uint32) charToWrite;
+
+ if (c >= 0x80)
+ {
+ ++num;
+ if (c >= 0x800)
+ {
+ ++num;
+ if (c >= 0x10000)
+ ++num;
+ }
+ }
+
+ return num;
+ }
+
+ /** Returns the number of bytes that would be needed to represent the given
+ string in this encoding format.
+ The value returned does NOT include the terminating null character.
+ */
+ template <class CharPointer>
+ static size_t getBytesRequiredFor (CharPointer text) noexcept
+ {
+ size_t count = 0;
+ juce_wchar n;
+
+ while ((n = text.getAndAdvance()) != 0)
+ count += getBytesRequiredFor (n);
+
+ return count;
+ }
+
+ /** Returns a pointer to the null character that terminates this string. */
+ CharPointer_UTF8 findTerminatingNull() const noexcept
+ {
+ return CharPointer_UTF8 (data + strlen (data));
+ }
+
+ /** Writes a unicode character to this string, and advances this pointer to point to the next position. */
+ void write (const juce_wchar charToWrite) noexcept
+ {
+ const uint32 c = (uint32) charToWrite;
+
+ if (c >= 0x80)
+ {
+ int numExtraBytes = 1;
+ if (c >= 0x800)
+ {
+ ++numExtraBytes;
+ if (c >= 0x10000)
+ ++numExtraBytes;
+ }
+
+ *data++ = (CharType) ((uint32) (0xff << (7 - numExtraBytes)) | (c >> (numExtraBytes * 6)));
+
+ while (--numExtraBytes >= 0)
+ *data++ = (CharType) (0x80 | (0x3f & (c >> (numExtraBytes * 6))));
+ }
+ else
+ {
+ *data++ = (CharType) c;
+ }
+ }
+
+ /** Writes a null character to this string (leaving the pointer's position unchanged). */
+ inline void writeNull() const noexcept
+ {
+ *data = 0;
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ template <typename CharPointer>
+ void writeAll (const CharPointer src) noexcept
+ {
+ CharacterFunctions::copyAll (*this, src);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes. */
+ void writeAll (const CharPointer_UTF8 src) noexcept
+ {
+ const CharType* s = src.data;
+
+ while ((*data = *s) != 0)
+ {
+ ++data;
+ ++s;
+ }
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxDestBytes parameter specifies the maximum number of bytes that can be written
+ to the destination buffer before stopping.
+ */
+ template <typename CharPointer>
+ size_t writeWithDestByteLimit (const CharPointer src, const size_t maxDestBytes) noexcept
+ {
+ return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes);
+ }
+
+ /** Copies a source string to this pointer, advancing this pointer as it goes.
+ The maxChars parameter specifies the maximum number of characters that can be
+ written to the destination buffer before stopping (including the terminating null).
+ */
+ template <typename CharPointer>
+ void writeWithCharLimit (const CharPointer src, const int maxChars) noexcept
+ {
+ CharacterFunctions::copyWithCharLimit (*this, src, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compare (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compare (*this, other);
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareUpTo (*this, other, maxChars);
+ }
+
+ /** Compares this string with another one. */
+ template <typename CharPointer>
+ int compareIgnoreCase (const CharPointer other) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCase (*this, other);
+ }
+
+ /** Compares this string with another one. */
+ int compareIgnoreCase (const CharPointer_UTF8 other) const noexcept
+ {
+ #if JUCE_WINDOWS
+ return stricmp (data, other.data);
+ #else
+ return strcasecmp (data, other.data);
+ #endif
+ }
+
+ /** Compares this string with another one, up to a specified number of characters. */
+ template <typename CharPointer>
+ int compareIgnoreCaseUpTo (const CharPointer other, const int maxChars) const noexcept
+ {
+ return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars);
+ }
+
+ /** Returns the character index of a substring, or -1 if it isn't found. */
+ template <typename CharPointer>
+ int indexOf (const CharPointer stringToFind) const noexcept
+ {
+ return CharacterFunctions::indexOf (*this, stringToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind) const noexcept
+ {
+ return CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns the character index of a unicode character, or -1 if it isn't found. */
+ int indexOf (const juce_wchar charToFind, const bool ignoreCase) const noexcept
+ {
+ return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind)
+ : CharacterFunctions::indexOfChar (*this, charToFind);
+ }
+
+ /** Returns true if the first character of this string is whitespace. */
+ bool isWhitespace() const noexcept { return *data == ' ' || (*data <= 13 && *data >= 9); }
+ /** Returns true if the first character of this string is a digit. */
+ bool isDigit() const noexcept { return *data >= '0' && *data <= '9'; }
+ /** Returns true if the first character of this string is a letter. */
+ bool isLetter() const noexcept { return CharacterFunctions::isLetter (operator*()) != 0; }
+ /** Returns true if the first character of this string is a letter or digit. */
+ bool isLetterOrDigit() const noexcept { return CharacterFunctions::isLetterOrDigit (operator*()) != 0; }
+ /** Returns true if the first character of this string is upper-case. */
+ bool isUpperCase() const noexcept { return CharacterFunctions::isUpperCase (operator*()) != 0; }
+ /** Returns true if the first character of this string is lower-case. */
+ bool isLowerCase() const noexcept { return CharacterFunctions::isLowerCase (operator*()) != 0; }
+
+ /** Returns an upper-case version of the first character of this string. */
+ juce_wchar toUpperCase() const noexcept { return CharacterFunctions::toUpperCase (operator*()); }
+ /** Returns a lower-case version of the first character of this string. */
+ juce_wchar toLowerCase() const noexcept { return CharacterFunctions::toLowerCase (operator*()); }
+
+ /** Parses this string as a 32-bit integer. */
+ int getIntValue32() const noexcept { return atoi (data); }
+
+ /** Parses this string as a 64-bit integer. */
+ int64 getIntValue64() const noexcept
+ {
+ #if JUCE_LINUX || JUCE_ANDROID
+ return atoll (data);
+ #elif JUCE_WINDOWS
+ return _atoi64 (data);
+ #else
+ return CharacterFunctions::getIntValue <int64, CharPointer_UTF8> (*this);
+ #endif
+ }
+
+ /** Parses this string as a floating point double. */
+ double getDoubleValue() const noexcept { return CharacterFunctions::getDoubleValue (*this); }
+
+ /** Returns the first non-whitespace character in the string. */
+ CharPointer_UTF8 findEndOfWhitespace() const noexcept { return CharacterFunctions::findEndOfWhitespace (*this); }
+
+ /** Returns true if the given unicode character can be represented in this encoding. */
+ static bool canRepresent (juce_wchar character) noexcept
+ {
+ return ((unsigned int) character) < (unsigned int) 0x10ffff;
+ }
+
+ /** Returns true if this data contains a valid string in this encoding. */
+ static bool isValidString (const CharType* dataToTest, int maxBytesToRead)
+ {
+ while (--maxBytesToRead >= 0 && *dataToTest != 0)
+ {
+ const signed char byte = (signed char) *dataToTest++;
+
+ if (byte < 0)
+ {
+ uint8 bit = 0x40;
+ int numExtraValues = 0;
+
+ while ((byte & bit) != 0)
+ {
+ if (bit < 8)
+ return false;
+
+ ++numExtraValues;
+ bit >>= 1;
+
+ if (bit == 8 && (numExtraValues > maxBytesToRead
+ || *CharPointer_UTF8 (dataToTest - 1) > 0x10ffff))
+ return false;
+ }
+
+ maxBytesToRead -= numExtraValues;
+ if (maxBytesToRead < 0)
+ return false;
+
+ while (--numExtraValues >= 0)
+ if ((*dataToTest++ & 0xc0) != 0x80)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /** Atomically swaps this pointer for a new value, returning the previous value. */
+ CharPointer_UTF8 atomicSwap (const CharPointer_UTF8 newValue)
+ {
+ return CharPointer_UTF8 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data));
+ }
+
+ /** These values are the byte-order mark (BOM) values for a UTF-8 stream. */
+ enum
+ {
+ byteOrderMark1 = 0xef,
+ byteOrderMark2 = 0xbb,
+ byteOrderMark3 = 0xbf
+ };
+
+ /** Returns true if the first three bytes in this pointer are the UTF8 byte-order mark (BOM).
+ The pointer must not be null, and must point to at least 3 valid bytes.
+ */
+ static bool isByteOrderMark (const void* possibleByteOrder) noexcept
+ {
+ jassert (possibleByteOrder != nullptr);
+ const uint8* const c = static_cast<const uint8*> (possibleByteOrder);
+
+ return c[0] == (uint8) byteOrderMark1
+ && c[1] == (uint8) byteOrderMark2
+ && c[2] == (uint8) byteOrderMark3;
+ }
+
+private:
+ CharType* data;
+};
+
+#endif // JUCE_CHARPOINTER_UTF8_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.cpp
new file mode 100644
index 0000000..11eaa18
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.cpp
@@ -0,0 +1,154 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+//==============================================================================
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4514 4996)
+#endif
+
+juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) noexcept
+{
+ return towupper ((wchar_t) character);
+}
+
+juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) noexcept
+{
+ return towlower ((wchar_t) character);
+}
+
+bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept
+{
+ #if JUCE_WINDOWS
+ return iswupper ((wchar_t) character) != 0;
+ #else
+ return toLowerCase (character) != character;
+ #endif
+}
+
+bool CharacterFunctions::isLowerCase (const juce_wchar character) noexcept
+{
+ #if JUCE_WINDOWS
+ return iswlower ((wchar_t) character) != 0;
+ #else
+ return toUpperCase (character) != character;
+ #endif
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+//==============================================================================
+bool CharacterFunctions::isWhitespace (const char character) noexcept
+{
+ return character == ' ' || (character <= 13 && character >= 9);
+}
+
+bool CharacterFunctions::isWhitespace (const juce_wchar character) noexcept
+{
+ return iswspace ((wchar_t) character) != 0;
+}
+
+bool CharacterFunctions::isDigit (const char character) noexcept
+{
+ return (character >= '0' && character <= '9');
+}
+
+bool CharacterFunctions::isDigit (const juce_wchar character) noexcept
+{
+ return iswdigit ((wchar_t) character) != 0;
+}
+
+bool CharacterFunctions::isLetter (const char character) noexcept
+{
+ return (character >= 'a' && character <= 'z')
+ || (character >= 'A' && character <= 'Z');
+}
+
+bool CharacterFunctions::isLetter (const juce_wchar character) noexcept
+{
+ return iswalpha ((wchar_t) character) != 0;
+}
+
+bool CharacterFunctions::isLetterOrDigit (const char character) noexcept
+{
+ return (character >= 'a' && character <= 'z')
+ || (character >= 'A' && character <= 'Z')
+ || (character >= '0' && character <= '9');
+}
+
+bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) noexcept
+{
+ return iswalnum ((wchar_t) character) != 0;
+}
+
+int CharacterFunctions::getHexDigitValue (const juce_wchar digit) noexcept
+{
+ unsigned int d = (unsigned int) digit - '0';
+ if (d < (unsigned int) 10)
+ return (int) d;
+
+ d += (unsigned int) ('0' - 'a');
+ if (d < (unsigned int) 6)
+ return (int) d + 10;
+
+ d += (unsigned int) ('a' - 'A');
+ if (d < (unsigned int) 6)
+ return (int) d + 10;
+
+ return -1;
+}
+
+double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept
+{
+ if (exponent == 0)
+ return value;
+
+ if (value == 0)
+ return 0;
+
+ const bool negative = (exponent < 0);
+ if (negative)
+ exponent = -exponent;
+
+ double result = 1.0, power = 10.0;
+ for (int bit = 1; exponent != 0; bit <<= 1)
+ {
+ if ((exponent & bit) != 0)
+ {
+ exponent ^= bit;
+ result *= power;
+ if (exponent == 0)
+ break;
+ }
+ power *= power;
+ }
+
+ return negative ? (value / result) : (value * result);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.h
new file mode 100644
index 0000000..bade0dd
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_CharacterFunctions.h
@@ -0,0 +1,629 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHARACTERFUNCTIONS_H_INCLUDED
+#define JUCE_CHARACTERFUNCTIONS_H_INCLUDED
+
+
+//==============================================================================
+#if JUCE_WINDOWS && ! DOXYGEN
+ #define JUCE_NATIVE_WCHAR_IS_UTF8 0
+ #define JUCE_NATIVE_WCHAR_IS_UTF16 1
+ #define JUCE_NATIVE_WCHAR_IS_UTF32 0
+#else
+ /** This macro will be set to 1 if the compiler's native wchar_t is an 8-bit type. */
+ #define JUCE_NATIVE_WCHAR_IS_UTF8 0
+ /** This macro will be set to 1 if the compiler's native wchar_t is a 16-bit type. */
+ #define JUCE_NATIVE_WCHAR_IS_UTF16 0
+ /** This macro will be set to 1 if the compiler's native wchar_t is a 32-bit type. */
+ #define JUCE_NATIVE_WCHAR_IS_UTF32 1
+#endif
+
+#if JUCE_NATIVE_WCHAR_IS_UTF32 || DOXYGEN
+ /** A platform-independent 32-bit unicode character type. */
+ typedef wchar_t juce_wchar;
+#else
+ typedef uint32 juce_wchar;
+#endif
+
+#ifndef DOXYGEN
+ /** This macro is deprecated, but preserved for compatibility with old code. */
+ #define JUCE_T(stringLiteral) (L##stringLiteral)
+#endif
+
+#if JUCE_DEFINE_T_MACRO
+ /** The 'T' macro is an alternative for using the "L" prefix in front of a string literal.
+
+ This macro is deprecated, but available for compatibility with old code if you set
+ JUCE_DEFINE_T_MACRO = 1. The fastest, most portable and best way to write your string
+ literals is as standard char strings, using escaped utf-8 character sequences for extended
+ characters, rather than trying to store them as wide-char strings.
+ */
+ #define T(stringLiteral) JUCE_T(stringLiteral)
+#endif
+
+//==============================================================================
+/**
+ A collection of functions for manipulating characters and character strings.
+
+ Most of these methods are designed for internal use by the String and CharPointer
+ classes, but some of them may be useful to call directly.
+
+ @see String, CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32
+*/
+class JUCE_API CharacterFunctions
+{
+public:
+ //==============================================================================
+ /** Converts a character to upper-case. */
+ static juce_wchar toUpperCase (juce_wchar character) noexcept;
+ /** Converts a character to lower-case. */
+ static juce_wchar toLowerCase (juce_wchar character) noexcept;
+
+ /** Checks whether a unicode character is upper-case. */
+ static bool isUpperCase (juce_wchar character) noexcept;
+ /** Checks whether a unicode character is lower-case. */
+ static bool isLowerCase (juce_wchar character) noexcept;
+
+ /** Checks whether a character is whitespace. */
+ static bool isWhitespace (char character) noexcept;
+ /** Checks whether a character is whitespace. */
+ static bool isWhitespace (juce_wchar character) noexcept;
+
+ /** Checks whether a character is a digit. */
+ static bool isDigit (char character) noexcept;
+ /** Checks whether a character is a digit. */
+ static bool isDigit (juce_wchar character) noexcept;
+
+ /** Checks whether a character is alphabetic. */
+ static bool isLetter (char character) noexcept;
+ /** Checks whether a character is alphabetic. */
+ static bool isLetter (juce_wchar character) noexcept;
+
+ /** Checks whether a character is alphabetic or numeric. */
+ static bool isLetterOrDigit (char character) noexcept;
+ /** Checks whether a character is alphabetic or numeric. */
+ static bool isLetterOrDigit (juce_wchar character) noexcept;
+
+ /** Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit. */
+ static int getHexDigitValue (juce_wchar digit) noexcept;
+
+ //==============================================================================
+ /** Parses a character string to read a floating-point number.
+ Note that this will advance the pointer that is passed in, leaving it at
+ the end of the number.
+ */
+ template <typename CharPointerType>
+ static double readDoubleValue (CharPointerType& text) noexcept
+ {
+ double result[3] = { 0 }, accumulator[2] = { 0 };
+ int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 };
+ int exponent = 0, decPointIndex = 0, digit = 0;
+ int lastDigit = 0, numSignificantDigits = 0;
+ bool isNegative = false, digitsFound = false;
+ const int maxSignificantDigits = 15 + 2;
+
+ text = text.findEndOfWhitespace();
+ juce_wchar c = *text;
+
+ switch (c)
+ {
+ case '-': isNegative = true; // fall-through..
+ case '+': c = *++text;
+ }
+
+ switch (c)
+ {
+ case 'n':
+ case 'N':
+ if ((text[1] == 'a' || text[1] == 'A') && (text[2] == 'n' || text[2] == 'N'))
+ return std::numeric_limits<double>::quiet_NaN();
+ break;
+
+ case 'i':
+ case 'I':
+ if ((text[1] == 'n' || text[1] == 'N') && (text[2] == 'f' || text[2] == 'F'))
+ return std::numeric_limits<double>::infinity();
+ break;
+ }
+
+ for (;;)
+ {
+ if (text.isDigit())
+ {
+ lastDigit = digit;
+ digit = (int) text.getAndAdvance() - '0';
+ digitsFound = true;
+
+ if (decPointIndex != 0)
+ exponentAdjustment[1]++;
+
+ if (numSignificantDigits == 0 && digit == 0)
+ continue;
+
+ if (++numSignificantDigits > maxSignificantDigits)
+ {
+ if (digit > 5)
+ ++accumulator [decPointIndex];
+ else if (digit == 5 && (lastDigit & 1) != 0)
+ ++accumulator [decPointIndex];
+
+ if (decPointIndex > 0)
+ exponentAdjustment[1]--;
+ else
+ exponentAdjustment[0]++;
+
+ while (text.isDigit())
+ {
+ ++text;
+ if (decPointIndex == 0)
+ exponentAdjustment[0]++;
+ }
+ }
+ else
+ {
+ const double maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
+ if (accumulator [decPointIndex] > maxAccumulatorValue)
+ {
+ result [decPointIndex] = mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
+ + accumulator [decPointIndex];
+ accumulator [decPointIndex] = 0;
+ exponentAccumulator [decPointIndex] = 0;
+ }
+
+ accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
+ exponentAccumulator [decPointIndex]++;
+ }
+ }
+ else if (decPointIndex == 0 && *text == '.')
+ {
+ ++text;
+ decPointIndex = 1;
+
+ if (numSignificantDigits > maxSignificantDigits)
+ {
+ while (text.isDigit())
+ ++text;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
+
+ if (decPointIndex != 0)
+ result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
+
+ c = *text;
+ if ((c == 'e' || c == 'E') && digitsFound)
+ {
+ bool negativeExponent = false;
+
+ switch (*++text)
+ {
+ case '-': negativeExponent = true; // fall-through..
+ case '+': ++text;
+ }
+
+ while (text.isDigit())
+ exponent = (exponent * 10) + ((int) text.getAndAdvance() - '0');
+
+ if (negativeExponent)
+ exponent = -exponent;
+ }
+
+ double r = mulexp10 (result[0], exponent + exponentAdjustment[0]);
+ if (decPointIndex != 0)
+ r += mulexp10 (result[1], exponent - exponentAdjustment[1]);
+
+ return isNegative ? -r : r;
+ }
+
+ /** Parses a character string, to read a floating-point value. */
+ template <typename CharPointerType>
+ static double getDoubleValue (CharPointerType text) noexcept
+ {
+ return readDoubleValue (text);
+ }
+
+ //==============================================================================
+ /** Parses a character string, to read an integer value. */
+ template <typename IntType, typename CharPointerType>
+ static IntType getIntValue (const CharPointerType text) noexcept
+ {
+ IntType v = 0;
+ CharPointerType s (text.findEndOfWhitespace());
+
+ const bool isNeg = *s == '-';
+ if (isNeg)
+ ++s;
+
+ for (;;)
+ {
+ const juce_wchar c = s.getAndAdvance();
+
+ if (c >= '0' && c <= '9')
+ v = v * 10 + (IntType) (c - '0');
+ else
+ break;
+ }
+
+ return isNeg ? -v : v;
+ }
+
+ template <typename ResultType>
+ struct HexParser
+ {
+ template <typename CharPointerType>
+ static ResultType parse (CharPointerType t) noexcept
+ {
+ ResultType result = 0;
+
+ while (! t.isEmpty())
+ {
+ const int hexValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
+
+ if (hexValue >= 0)
+ result = (result << 4) | hexValue;
+ }
+
+ return result;
+ }
+ };
+
+ //==============================================================================
+ /** Counts the number of characters in a given string, stopping if the count exceeds
+ a specified limit. */
+ template <typename CharPointerType>
+ static size_t lengthUpTo (CharPointerType text, const size_t maxCharsToCount) noexcept
+ {
+ size_t len = 0;
+
+ while (len < maxCharsToCount && text.getAndAdvance() != 0)
+ ++len;
+
+ return len;
+ }
+
+ /** Counts the number of characters in a given string, stopping if the count exceeds
+ a specified end-pointer. */
+ template <typename CharPointerType>
+ static size_t lengthUpTo (CharPointerType start, const CharPointerType end) noexcept
+ {
+ size_t len = 0;
+
+ while (start < end && start.getAndAdvance() != 0)
+ ++len;
+
+ return len;
+ }
+
+ /** Copies null-terminated characters from one string to another. */
+ template <typename DestCharPointerType, typename SrcCharPointerType>
+ static void copyAll (DestCharPointerType& dest, SrcCharPointerType src) noexcept
+ {
+ for (;;)
+ {
+ const juce_wchar c = src.getAndAdvance();
+
+ if (c == 0)
+ break;
+
+ dest.write (c);
+ }
+
+ dest.writeNull();
+ }
+
+ /** Copies characters from one string to another, up to a null terminator
+ or a given byte size limit. */
+ template <typename DestCharPointerType, typename SrcCharPointerType>
+ static size_t copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept
+ {
+ typename DestCharPointerType::CharType const* const startAddress = dest.getAddress();
+ ssize_t maxBytes = (ssize_t) maxBytesToWrite;
+ maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null)
+
+ for (;;)
+ {
+ const juce_wchar c = src.getAndAdvance();
+ const size_t bytesNeeded = DestCharPointerType::getBytesRequiredFor (c);
+
+ maxBytes -= bytesNeeded;
+ if (c == 0 || maxBytes < 0)
+ break;
+
+ dest.write (c);
+ }
+
+ dest.writeNull();
+
+ return (size_t) getAddressDifference (dest.getAddress(), startAddress)
+ + sizeof (typename DestCharPointerType::CharType);
+ }
+
+ /** Copies characters from one string to another, up to a null terminator
+ or a given maximum number of characters. */
+ template <typename DestCharPointerType, typename SrcCharPointerType>
+ static void copyWithCharLimit (DestCharPointerType& dest, SrcCharPointerType src, int maxChars) noexcept
+ {
+ while (--maxChars > 0)
+ {
+ const juce_wchar c = src.getAndAdvance();
+ if (c == 0)
+ break;
+
+ dest.write (c);
+ }
+
+ dest.writeNull();
+ }
+
+ /** Compares two null-terminated character strings. */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int compare (CharPointerType1 s1, CharPointerType2 s2) noexcept
+ {
+ for (;;)
+ {
+ const int c1 = (int) s1.getAndAdvance();
+ const int c2 = (int) s2.getAndAdvance();
+ const int diff = c1 - c2;
+
+ if (diff != 0) return diff < 0 ? -1 : 1;
+ if (c1 == 0) break;
+ }
+
+ return 0;
+ }
+
+ /** Compares two null-terminated character strings, up to a given number of characters. */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int compareUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
+ {
+ while (--maxChars >= 0)
+ {
+ const int c1 = (int) s1.getAndAdvance();
+ const int c2 = (int) s2.getAndAdvance();
+ const int diff = c1 - c2;
+
+ if (diff != 0) return diff < 0 ? -1 : 1;
+ if (c1 == 0) break;
+ }
+
+ return 0;
+ }
+
+ /** Compares two null-terminated character strings, using a case-independant match. */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int compareIgnoreCase (CharPointerType1 s1, CharPointerType2 s2) noexcept
+ {
+ for (;;)
+ {
+ const int c1 = (int) s1.toUpperCase();
+ const int c2 = (int) s2.toUpperCase();
+ const int diff = c1 - c2;
+
+ if (diff != 0) return diff < 0 ? -1 : 1;
+ if (c1 == 0) break;
+
+ ++s1; ++s2;
+ }
+
+ return 0;
+ }
+
+ /** Compares two null-terminated character strings, using a case-independent match. */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int compareIgnoreCaseUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
+ {
+ while (--maxChars >= 0)
+ {
+ const int c1 = (int) s1.toUpperCase();
+ const int c2 = (int) s2.toUpperCase();
+ const int diff = c1 - c2;
+
+ if (diff != 0) return diff < 0 ? -1 : 1;
+ if (c1 == 0) break;
+
+ ++s1; ++s2;
+ }
+
+ return 0;
+ }
+
+ /** Finds the character index of a given substring in another string.
+ Returns -1 if the substring is not found.
+ */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int indexOf (CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
+ {
+ int index = 0;
+ const int substringLength = (int) substringToLookFor.length();
+
+ for (;;)
+ {
+ if (textToSearch.compareUpTo (substringToLookFor, substringLength) == 0)
+ return index;
+
+ if (textToSearch.getAndAdvance() == 0)
+ return -1;
+
+ ++index;
+ }
+ }
+
+ /** Returns a pointer to the first occurrence of a substring in a string.
+ If the substring is not found, this will return a pointer to the string's
+ null terminator.
+ */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static CharPointerType1 find (CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
+ {
+ const int substringLength = (int) substringToLookFor.length();
+
+ while (textToSearch.compareUpTo (substringToLookFor, substringLength) != 0
+ && ! textToSearch.isEmpty())
+ ++textToSearch;
+
+ return textToSearch;
+ }
+
+ /** Returns a pointer to the first occurrence of a substring in a string.
+ If the substring is not found, this will return a pointer to the string's
+ null terminator.
+ */
+ template <typename CharPointerType>
+ static CharPointerType find (CharPointerType textToSearch, const juce_wchar charToLookFor) noexcept
+ {
+ for (;; ++textToSearch)
+ {
+ const juce_wchar c = *textToSearch;
+
+ if (c == charToLookFor || c == 0)
+ break;
+ }
+
+ return textToSearch;
+ }
+
+ /** Finds the character index of a given substring in another string, using
+ a case-independent match.
+ Returns -1 if the substring is not found.
+ */
+ template <typename CharPointerType1, typename CharPointerType2>
+ static int indexOfIgnoreCase (CharPointerType1 haystack, const CharPointerType2 needle) noexcept
+ {
+ int index = 0;
+ const int needleLength = (int) needle.length();
+
+ for (;;)
+ {
+ if (haystack.compareIgnoreCaseUpTo (needle, needleLength) == 0)
+ return index;
+
+ if (haystack.getAndAdvance() == 0)
+ return -1;
+
+ ++index;
+ }
+ }
+
+ /** Finds the character index of a given character in another string.
+ Returns -1 if the character is not found.
+ */
+ template <typename Type>
+ static int indexOfChar (Type text, const juce_wchar charToFind) noexcept
+ {
+ int i = 0;
+
+ while (! text.isEmpty())
+ {
+ if (text.getAndAdvance() == charToFind)
+ return i;
+
+ ++i;
+ }
+
+ return -1;
+ }
+
+ /** Finds the character index of a given character in another string, using
+ a case-independent match.
+ Returns -1 if the character is not found.
+ */
+ template <typename Type>
+ static int indexOfCharIgnoreCase (Type text, juce_wchar charToFind) noexcept
+ {
+ charToFind = CharacterFunctions::toLowerCase (charToFind);
+ int i = 0;
+
+ while (! text.isEmpty())
+ {
+ if (text.toLowerCase() == charToFind)
+ return i;
+
+ ++text;
+ ++i;
+ }
+
+ return -1;
+ }
+
+ /** Returns a pointer to the first non-whitespace character in a string.
+ If the string contains only whitespace, this will return a pointer
+ to its null terminator.
+ */
+ template <typename Type>
+ static Type findEndOfWhitespace (Type text) noexcept
+ {
+ while (text.isWhitespace())
+ ++text;
+
+ return text;
+ }
+
+ /** Returns a pointer to the first character in the string which is found in
+ the breakCharacters string.
+ */
+ template <typename Type, typename BreakType>
+ static Type findEndOfToken (Type text, const BreakType breakCharacters, const Type quoteCharacters)
+ {
+ juce_wchar currentQuoteChar = 0;
+
+ while (! text.isEmpty())
+ {
+ const juce_wchar c = text.getAndAdvance();
+
+ if (currentQuoteChar == 0 && breakCharacters.indexOf (c) >= 0)
+ {
+ --text;
+ break;
+ }
+
+ if (quoteCharacters.indexOf (c) >= 0)
+ {
+ if (currentQuoteChar == 0)
+ currentQuoteChar = c;
+ else if (currentQuoteChar == c)
+ currentQuoteChar = 0;
+ }
+ }
+
+ return text;
+ }
+
+private:
+ static double mulexp10 (const double value, int exponent) noexcept;
+};
+
+
+#endif // JUCE_CHARACTERFUNCTIONS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.cpp
new file mode 100644
index 0000000..bac4dd5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.cpp
@@ -0,0 +1,70 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Identifier::Identifier() noexcept {}
+Identifier::~Identifier() noexcept {}
+
+Identifier::Identifier (const Identifier& other) noexcept : name (other.name) {}
+
+Identifier& Identifier::operator= (const Identifier other) noexcept
+{
+ name = other.name;
+ return *this;
+}
+
+Identifier::Identifier (const String& nm)
+ : name (StringPool::getGlobalPool().getPooledString (nm))
+{
+ /* An Identifier string must be suitable for use as a script variable or XML
+ attribute, so it can only contain this limited set of characters.. */
+ jassert (isValidIdentifier (toString()));
+}
+
+Identifier::Identifier (const char* nm)
+ : name (StringPool::getGlobalPool().getPooledString (nm))
+{
+ /* An Identifier string must be suitable for use as a script variable or XML
+ attribute, so it can only contain this limited set of characters.. */
+ jassert (isValidIdentifier (toString()));
+}
+
+Identifier::Identifier (String::CharPointerType start, String::CharPointerType end)
+ : name (StringPool::getGlobalPool().getPooledString (start, end))
+{
+ /* An Identifier string must be suitable for use as a script variable or XML
+ attribute, so it can only contain this limited set of characters.. */
+ jassert (isValidIdentifier (toString()));
+}
+
+Identifier Identifier::null;
+
+bool Identifier::isValidIdentifier (const String& possibleIdentifier) noexcept
+{
+ return possibleIdentifier.isNotEmpty()
+ && possibleIdentifier.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:#@$%");
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.h
new file mode 100644
index 0000000..f60eec8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_Identifier.h
@@ -0,0 +1,120 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_IDENTIFIER_H_INCLUDED
+#define JUCE_IDENTIFIER_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Represents a string identifier, designed for accessing properties by name.
+
+ Comparing two Identifier objects is very fast (an O(1) operation), but creating
+ them can be slower than just using a String directly, so the optimal way to use them
+ is to keep some static Identifier objects for the things you use often.
+
+ @see NamedValueSet, ValueTree
+*/
+class JUCE_API Identifier
+{
+public:
+ /** Creates a null identifier. */
+ Identifier() noexcept;
+
+ /** Creates an identifier with a specified name.
+ Because this name may need to be used in contexts such as script variables or XML
+ tags, it must only contain ascii letters and digits, or the underscore character.
+ */
+ Identifier (const char* name);
+
+ /** Creates an identifier with a specified name.
+ Because this name may need to be used in contexts such as script variables or XML
+ tags, it must only contain ascii letters and digits, or the underscore character.
+ */
+ Identifier (const String& name);
+
+ /** Creates an identifier with a specified name.
+ Because this name may need to be used in contexts such as script variables or XML
+ tags, it must only contain ascii letters and digits, or the underscore character.
+ */
+ Identifier (String::CharPointerType nameStart, String::CharPointerType nameEnd);
+
+ /** Creates a copy of another identifier. */
+ Identifier (const Identifier& other) noexcept;
+
+ /** Creates a copy of another identifier. */
+ Identifier& operator= (const Identifier other) noexcept;
+
+ /** Destructor */
+ ~Identifier() noexcept;
+
+ /** Compares two identifiers. This is a very fast operation. */
+ inline bool operator== (Identifier other) const noexcept { return name.getCharPointer() == other.name.getCharPointer(); }
+
+ /** Compares two identifiers. This is a very fast operation. */
+ inline bool operator!= (Identifier other) const noexcept { return name.getCharPointer() != other.name.getCharPointer(); }
+
+ /** Compares the identifier with a string. */
+ inline bool operator== (StringRef other) const noexcept { return name == other; }
+
+ /** Compares the identifier with a string. */
+ inline bool operator!= (StringRef other) const noexcept { return name != other; }
+
+ /** Returns this identifier as a string. */
+ const String& toString() const noexcept { return name; }
+
+ /** Returns this identifier's raw string pointer. */
+ operator String::CharPointerType() const noexcept { return name.getCharPointer(); }
+
+ /** Returns this identifier's raw string pointer. */
+ String::CharPointerType getCharPointer() const noexcept { return name.getCharPointer(); }
+
+ /** Returns this identifier as a StringRef. */
+ operator StringRef() const noexcept { return name; }
+
+ /** Returns true if this Identifier is not null */
+ bool isValid() const noexcept { return name.isNotEmpty(); }
+
+ /** Returns true if this Identifier is null */
+ bool isNull() const noexcept { return name.isEmpty(); }
+
+ /** A null identifier. */
+ static Identifier null;
+
+ /** Checks a given string for characters that might not be valid in an Identifier.
+ Since Identifiers are used as a script variables and XML attributes, they should only contain
+ alphanumeric characters, underscores, or the '-' and ':' characters.
+ */
+ static bool isValidIdentifier (const String& possibleIdentifier) noexcept;
+
+private:
+ String name;
+};
+
+
+#endif // JUCE_IDENTIFIER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.cpp
new file mode 100644
index 0000000..e6118d3
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.cpp
@@ -0,0 +1,209 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+LocalisedStrings::LocalisedStrings (const String& fileContents, bool ignoreCase)
+{
+ loadFromText (fileContents, ignoreCase);
+}
+
+LocalisedStrings::LocalisedStrings (const File& fileToLoad, bool ignoreCase)
+{
+ loadFromText (fileToLoad.loadFileAsString(), ignoreCase);
+}
+
+LocalisedStrings::LocalisedStrings (const LocalisedStrings& other)
+ : languageName (other.languageName), countryCodes (other.countryCodes),
+ translations (other.translations), fallback (createCopyIfNotNull (other.fallback.get()))
+{
+}
+
+LocalisedStrings& LocalisedStrings::operator= (const LocalisedStrings& other)
+{
+ languageName = other.languageName;
+ countryCodes = other.countryCodes;
+ translations = other.translations;
+ fallback = createCopyIfNotNull (other.fallback.get());
+ return *this;
+}
+
+LocalisedStrings::~LocalisedStrings()
+{
+}
+
+//==============================================================================
+String LocalisedStrings::translate (const String& text) const
+{
+ if (fallback != nullptr && ! translations.containsKey (text))
+ return fallback->translate (text);
+
+ return translations.getValue (text, text);
+}
+
+String LocalisedStrings::translate (const String& text, const String& resultIfNotFound) const
+{
+ if (fallback != nullptr && ! translations.containsKey (text))
+ return fallback->translate (text, resultIfNotFound);
+
+ return translations.getValue (text, resultIfNotFound);
+}
+
+namespace
+{
+ #if JUCE_CHECK_MEMORY_LEAKS
+ // By using this object to force a LocalisedStrings object to be created
+ // before the currentMappings object, we can force the static order-of-destruction to
+ // delete the currentMappings object first, which avoids a bogus leak warning.
+ // (Oddly, just creating a LocalisedStrings on the stack doesn't work in gcc, it
+ // has to be created with 'new' for this to work..)
+ struct LeakAvoidanceTrick
+ {
+ LeakAvoidanceTrick()
+ {
+ const ScopedPointer<LocalisedStrings> dummy (new LocalisedStrings (String(), false));
+ }
+ };
+
+ LeakAvoidanceTrick leakAvoidanceTrick;
+ #endif
+
+ SpinLock currentMappingsLock;
+ ScopedPointer<LocalisedStrings> currentMappings;
+
+ static int findCloseQuote (const String& text, int startPos)
+ {
+ juce_wchar lastChar = 0;
+ String::CharPointerType t (text.getCharPointer() + startPos);
+
+ for (;;)
+ {
+ const juce_wchar c = t.getAndAdvance();
+
+ if (c == 0 || (c == '"' && lastChar != '\\'))
+ break;
+
+ lastChar = c;
+ ++startPos;
+ }
+
+ return startPos;
+ }
+
+ static String unescapeString (const String& s)
+ {
+ return s.replace ("\\\"", "\"")
+ .replace ("\\\'", "\'")
+ .replace ("\\t", "\t")
+ .replace ("\\r", "\r")
+ .replace ("\\n", "\n");
+ }
+}
+
+void LocalisedStrings::loadFromText (const String& fileContents, bool ignoreCase)
+{
+ translations.setIgnoresCase (ignoreCase);
+
+ StringArray lines;
+ lines.addLines (fileContents);
+
+ for (int i = 0; i < lines.size(); ++i)
+ {
+ String line (lines[i].trim());
+
+ if (line.startsWithChar ('"'))
+ {
+ int closeQuote = findCloseQuote (line, 1);
+
+ const String originalText (unescapeString (line.substring (1, closeQuote)));
+
+ if (originalText.isNotEmpty())
+ {
+ const int openingQuote = findCloseQuote (line, closeQuote + 1);
+ closeQuote = findCloseQuote (line, openingQuote + 1);
+
+ const String newText (unescapeString (line.substring (openingQuote + 1, closeQuote)));
+
+ if (newText.isNotEmpty())
+ translations.set (originalText, newText);
+ }
+ }
+ else if (line.startsWithIgnoreCase ("language:"))
+ {
+ languageName = line.substring (9).trim();
+ }
+ else if (line.startsWithIgnoreCase ("countries:"))
+ {
+ countryCodes.addTokens (line.substring (10).trim(), true);
+ countryCodes.trim();
+ countryCodes.removeEmptyStrings();
+ }
+ }
+
+ translations.minimiseStorageOverheads();
+}
+
+void LocalisedStrings::addStrings (const LocalisedStrings& other)
+{
+ jassert (languageName == other.languageName);
+ jassert (countryCodes == other.countryCodes);
+
+ translations.addArray (other.translations);
+}
+
+void LocalisedStrings::setFallback (LocalisedStrings* f)
+{
+ fallback = f;
+}
+
+//==============================================================================
+void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations)
+{
+ const SpinLock::ScopedLockType sl (currentMappingsLock);
+ currentMappings = newTranslations;
+}
+
+LocalisedStrings* LocalisedStrings::getCurrentMappings()
+{
+ return currentMappings;
+}
+
+String LocalisedStrings::translateWithCurrentMappings (const String& text) { return juce::translate (text); }
+String LocalisedStrings::translateWithCurrentMappings (const char* text) { return juce::translate (text); }
+
+JUCE_API String translate (const String& text) { return juce::translate (text, text); }
+JUCE_API String translate (const char* text) { return juce::translate (String (text)); }
+JUCE_API String translate (CharPointer_UTF8 text) { return juce::translate (String (text)); }
+
+JUCE_API String translate (const String& text, const String& resultIfNotFound)
+{
+ const SpinLock::ScopedLockType sl (currentMappingsLock);
+
+ if (const LocalisedStrings* const mappings = LocalisedStrings::getCurrentMappings())
+ return mappings->translate (text, resultIfNotFound);
+
+ return resultIfNotFound;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.h
new file mode 100644
index 0000000..a594919
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_LocalisedStrings.h
@@ -0,0 +1,247 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_LOCALISEDSTRINGS_H_INCLUDED
+#define JUCE_LOCALISEDSTRINGS_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Used to convert strings to localised foreign-language versions.
+
+ This is basically a look-up table of strings and their translated equivalents.
+ It can be loaded from a text file, so that you can supply a set of localised
+ versions of strings that you use in your app.
+
+ To use it in your code, simply call the translate() method on each string that
+ might have foreign versions, and if none is found, the method will just return
+ the original string.
+
+ The translation file should start with some lines specifying a description of
+ the language it contains, and also a list of ISO country codes where it might
+ be appropriate to use the file. After that, each line of the file should contain
+ a pair of quoted strings with an '=' sign.
+
+ E.g. for a french translation, the file might be:
+
+ @code
+ language: French
+ countries: fr be mc ch lu
+
+ "hello" = "bonjour"
+ "goodbye" = "au revoir"
+ @endcode
+
+ If the strings need to contain a quote character, they can use '\"' instead, and
+ if the first non-whitespace character on a line isn't a quote, then it's ignored,
+ (you can use this to add comments).
+
+ Note that this is a singleton class, so don't create or destroy the object directly.
+ There's also a TRANS(text) macro defined to make it easy to use the this.
+
+ E.g. @code
+ printSomething (TRANS("hello"));
+ @endcode
+
+ This macro is used in the Juce classes themselves, so your application has a chance to
+ intercept and translate any internal Juce text strings that might be shown. (You can easily
+ get a list of all the messages by searching for the TRANS() macro in the Juce source
+ code).
+*/
+class JUCE_API LocalisedStrings
+{
+public:
+ //==============================================================================
+ /** Creates a set of translations from the text of a translation file.
+
+ When you create one of these, you can call setCurrentMappings() to make it
+ the set of mappings that the system's using.
+ */
+ LocalisedStrings (const String& fileContents, bool ignoreCaseOfKeys);
+
+ /** Creates a set of translations from a file.
+
+ When you create one of these, you can call setCurrentMappings() to make it
+ the set of mappings that the system's using.
+ */
+ LocalisedStrings (const File& fileToLoad, bool ignoreCaseOfKeys);
+
+ LocalisedStrings (const LocalisedStrings&);
+ LocalisedStrings& operator= (const LocalisedStrings&);
+
+ /** Destructor. */
+ ~LocalisedStrings();
+
+ //==============================================================================
+ /** Selects the current set of mappings to be used by the system.
+
+ The object you pass in will be automatically deleted when no longer needed, so
+ don't keep a pointer to it. You can also pass in nullptr to remove the current
+ mappings.
+
+ See also the TRANS() macro, which uses the current set to do its translation.
+
+ @see translateWithCurrentMappings
+ */
+ static void setCurrentMappings (LocalisedStrings* newTranslations);
+
+ /** Returns the currently selected set of mappings.
+
+ This is the object that was last passed to setCurrentMappings(). It may
+ be nullptr if none has been created.
+ */
+ static LocalisedStrings* getCurrentMappings();
+
+ /** Tries to translate a string using the currently selected set of mappings.
+
+ If no mapping has been set, or if the mapping doesn't contain a translation
+ for the string, this will just return the original string.
+
+ See also the TRANS() macro, which uses this method to do its translation.
+
+ @see setCurrentMappings, getCurrentMappings
+ */
+ static String translateWithCurrentMappings (const String& text);
+
+ /** Tries to translate a string using the currently selected set of mappings.
+
+ If no mapping has been set, or if the mapping doesn't contain a translation
+ for the string, this will just return the original string.
+
+ See also the TRANS() macro, which uses this method to do its translation.
+
+ @see setCurrentMappings, getCurrentMappings
+ */
+ static String translateWithCurrentMappings (const char* text);
+
+ //==============================================================================
+ /** Attempts to look up a string and return its localised version.
+ If the string isn't found in the list, the original string will be returned.
+ */
+ String translate (const String& text) const;
+
+ /** Attempts to look up a string and return its localised version.
+ If the string isn't found in the list, the resultIfNotFound string will be returned.
+ */
+ String translate (const String& text, const String& resultIfNotFound) const;
+
+ /** Returns the name of the language specified in the translation file.
+
+ This is specified in the file using a line starting with "language:", e.g.
+ @code
+ language: german
+ @endcode
+ */
+ String getLanguageName() const { return languageName; }
+
+ /** Returns the list of suitable country codes listed in the translation file.
+
+ These is specified in the file using a line starting with "countries:", e.g.
+ @code
+ countries: fr be mc ch lu
+ @endcode
+
+ The country codes are supposed to be 2-character ISO complient codes.
+ */
+ const StringArray& getCountryCodes() const { return countryCodes; }
+
+ /** Provides access to the actual list of mappings. */
+ const StringPairArray& getMappings() const { return translations; }
+
+ //==============================================================================
+ /** Adds and merges another set of translations into this set.
+
+ Note that the language name and country codes of the new LocalisedStrings
+ object must match that of this object - an assertion will be thrown if they
+ don't match.
+
+ Any existing values will have their mappings overwritten by the new ones.
+ */
+ void addStrings (const LocalisedStrings&);
+
+ /** Gives this object a set of strings to use as a fallback if a string isn't found.
+ The object that is passed-in will be owned and deleted by this object
+ when no longer needed. It can be nullptr to clear the existing fallback object.
+ */
+ void setFallback (LocalisedStrings* fallbackStrings);
+
+private:
+ //==============================================================================
+ String languageName;
+ StringArray countryCodes;
+ StringPairArray translations;
+ ScopedPointer<LocalisedStrings> fallback;
+ friend struct ContainerDeletePolicy<LocalisedStrings>;
+
+ void loadFromText (const String&, bool ignoreCase);
+
+ JUCE_LEAK_DETECTOR (LocalisedStrings)
+};
+
+//==============================================================================
+#ifndef TRANS
+ /** Uses the LocalisedStrings class to translate the given string literal.
+ This macro is provided for backwards-compatibility, and just calls the translate()
+ function. In new code, it's recommended that you just call translate() directly
+ instead, and avoid using macros.
+ @see translate(), LocalisedStrings
+ */
+ #define TRANS(stringLiteral) juce::translate (stringLiteral)
+#endif
+
+/** A dummy version of the TRANS macro, used to indicate a string literal that should be
+ added to the translation file by source-code scanner tools.
+
+ Wrapping a string literal in this macro has no effect, but by using it around strings
+ that your app needs to translate at a later stage, it lets automatic code-scanning tools
+ find this string and add it to the list of strings that need translation.
+*/
+#define NEEDS_TRANS(stringLiteral) (stringLiteral)
+
+/** Uses the LocalisedStrings class to translate the given string literal.
+ @see LocalisedStrings
+*/
+JUCE_API String translate (const String& stringLiteral);
+
+/** Uses the LocalisedStrings class to translate the given string literal.
+ @see LocalisedStrings
+*/
+JUCE_API String translate (const char* stringLiteral);
+
+/** Uses the LocalisedStrings class to translate the given string literal.
+ @see LocalisedStrings
+*/
+JUCE_API String translate (CharPointer_UTF8 stringLiteral);
+
+/** Uses the LocalisedStrings class to translate the given string literal.
+ @see LocalisedStrings
+*/
+JUCE_API String translate (const String& stringLiteral, const String& resultIfNotFound);
+
+
+#endif // JUCE_LOCALISEDSTRINGS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_NewLine.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_NewLine.h
new file mode 100644
index 0000000..980ac23
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_NewLine.h
@@ -0,0 +1,86 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_NEWLINE_H_INCLUDED
+#define JUCE_NEWLINE_H_INCLUDED
+
+
+//==============================================================================
+/** This class is used for represent a new-line character sequence.
+
+ To write a new-line to a stream, you can use the predefined 'newLine' variable, e.g.
+ @code
+ myOutputStream << "Hello World" << newLine << newLine;
+ @endcode
+
+ The exact character sequence that will be used for the new-line can be set and
+ retrieved with OutputStream::setNewLineString() and OutputStream::getNewLineString().
+*/
+class JUCE_API NewLine
+{
+public:
+ /** Returns the default new-line sequence that the library uses.
+ @see OutputStream::setNewLineString()
+ */
+ static const char* getDefault() noexcept { return "\r\n"; }
+
+ /** Returns the default new-line sequence that the library uses.
+ @see getDefault()
+ */
+ operator String() const { return getDefault(); }
+
+ /** Returns the default new-line sequence that the library uses.
+ @see OutputStream::setNewLineString()
+ */
+ operator StringRef() const noexcept { return getDefault(); }
+};
+
+//==============================================================================
+/** A predefined object representing a new-line, which can be written to a string or stream.
+
+ To write a new-line to a stream, you can use the predefined 'newLine' variable like this:
+ @code
+ myOutputStream << "Hello World" << newLine << newLine;
+ @endcode
+*/
+extern NewLine newLine;
+
+//==============================================================================
+/** Writes a new-line sequence to a string.
+ You can use the predefined object 'newLine' to invoke this, e.g.
+ @code
+ myString << "Hello World" << newLine << newLine;
+ @endcode
+*/
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&);
+
+#if JUCE_STRING_UTF_TYPE != 8 && ! defined (DOXYGEN)
+ inline String operator+ (String s1, const NewLine&) { return s1 += NewLine::getDefault(); }
+#endif
+
+#endif // JUCE_NEWLINE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.cpp
new file mode 100644
index 0000000..1dce723
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.cpp
@@ -0,0 +1,2543 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4514 4996)
+#endif
+
+NewLine newLine;
+
+#if defined (JUCE_STRINGS_ARE_UNICODE) && ! JUCE_STRINGS_ARE_UNICODE
+ #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default."
+#endif
+
+#if JUCE_NATIVE_WCHAR_IS_UTF8
+ typedef CharPointer_UTF8 CharPointer_wchar_t;
+#elif JUCE_NATIVE_WCHAR_IS_UTF16
+ typedef CharPointer_UTF16 CharPointer_wchar_t;
+#else
+ typedef CharPointer_UTF32 CharPointer_wchar_t;
+#endif
+
+static inline CharPointer_wchar_t castToCharPointer_wchar_t (const void* t) noexcept
+{
+ return CharPointer_wchar_t (static_cast<const CharPointer_wchar_t::CharType*> (t));
+}
+
+//==============================================================================
+// (Mirrors the structure of StringHolder, but without the atomic member, so can be statically constructed)
+struct EmptyString
+{
+ int refCount;
+ size_t allocatedBytes;
+ String::CharPointerType::CharType text;
+};
+
+static const EmptyString emptyString = { 0x3fffffff, sizeof (String::CharPointerType::CharType), 0 };
+
+//==============================================================================
+class StringHolder
+{
+public:
+ StringHolder() JUCE_DELETED_FUNCTION;
+
+ typedef String::CharPointerType CharPointerType;
+ typedef String::CharPointerType::CharType CharType;
+
+ //==============================================================================
+ static CharPointerType createUninitialisedBytes (size_t numBytes)
+ {
+ numBytes = (numBytes + 3) & ~(size_t) 3;
+ StringHolder* const s = reinterpret_cast<StringHolder*> (new char [sizeof (StringHolder) - sizeof (CharType) + numBytes]);
+ s->refCount.value = 0;
+ s->allocatedNumBytes = numBytes;
+ return CharPointerType (s->text);
+ }
+
+ template <class CharPointer>
+ static CharPointerType createFromCharPointer (const CharPointer text)
+ {
+ if (text.getAddress() == nullptr || text.isEmpty())
+ return CharPointerType (&(emptyString.text));
+
+ CharPointer t (text);
+ size_t bytesNeeded = sizeof (CharType);
+
+ while (! t.isEmpty())
+ bytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance());
+
+ const CharPointerType dest (createUninitialisedBytes (bytesNeeded));
+ CharPointerType (dest).writeAll (text);
+ return dest;
+ }
+
+ template <class CharPointer>
+ static CharPointerType createFromCharPointer (const CharPointer text, size_t maxChars)
+ {
+ if (text.getAddress() == nullptr || text.isEmpty() || maxChars == 0)
+ return CharPointerType (&(emptyString.text));
+
+ CharPointer end (text);
+ size_t numChars = 0;
+ size_t bytesNeeded = sizeof (CharType);
+
+ while (numChars < maxChars && ! end.isEmpty())
+ {
+ bytesNeeded += CharPointerType::getBytesRequiredFor (end.getAndAdvance());
+ ++numChars;
+ }
+
+ const CharPointerType dest (createUninitialisedBytes (bytesNeeded));
+ CharPointerType (dest).writeWithCharLimit (text, (int) numChars + 1);
+ return dest;
+ }
+
+ template <class CharPointer>
+ static CharPointerType createFromCharPointer (const CharPointer start, const CharPointer end)
+ {
+ if (start.getAddress() == nullptr || start.isEmpty())
+ return CharPointerType (&(emptyString.text));
+
+ CharPointer e (start);
+ int numChars = 0;
+ size_t bytesNeeded = sizeof (CharType);
+
+ while (e < end && ! e.isEmpty())
+ {
+ bytesNeeded += CharPointerType::getBytesRequiredFor (e.getAndAdvance());
+ ++numChars;
+ }
+
+ const CharPointerType dest (createUninitialisedBytes (bytesNeeded));
+ CharPointerType (dest).writeWithCharLimit (start, numChars + 1);
+ return dest;
+ }
+
+ static CharPointerType createFromCharPointer (const CharPointerType start, const CharPointerType end)
+ {
+ if (start.getAddress() == nullptr || start.isEmpty())
+ return CharPointerType (&(emptyString.text));
+
+ const size_t numBytes = (size_t) (reinterpret_cast<const char*> (end.getAddress())
+ - reinterpret_cast<const char*> (start.getAddress()));
+ const CharPointerType dest (createUninitialisedBytes (numBytes + sizeof (CharType)));
+ memcpy (dest.getAddress(), start, numBytes);
+ dest.getAddress()[numBytes / sizeof (CharType)] = 0;
+ return dest;
+ }
+
+ static CharPointerType createFromFixedLength (const char* const src, const size_t numChars)
+ {
+ const CharPointerType dest (createUninitialisedBytes (numChars * sizeof (CharType) + sizeof (CharType)));
+ CharPointerType (dest).writeWithCharLimit (CharPointer_UTF8 (src), (int) (numChars + 1));
+ return dest;
+ }
+
+ //==============================================================================
+ static void retain (const CharPointerType text) noexcept
+ {
+ StringHolder* const b = bufferFromText (text);
+
+ if (b != (StringHolder*) &emptyString)
+ ++(b->refCount);
+ }
+
+ static inline void release (StringHolder* const b) noexcept
+ {
+ if (b != (StringHolder*) &emptyString)
+ if (--(b->refCount) == -1)
+ delete[] reinterpret_cast<char*> (b);
+ }
+
+ static void release (const CharPointerType text) noexcept
+ {
+ release (bufferFromText (text));
+ }
+
+ static inline int getReferenceCount (const CharPointerType text) noexcept
+ {
+ return bufferFromText (text)->refCount.get() + 1;
+ }
+
+ //==============================================================================
+ static CharPointerType makeUniqueWithByteSize (const CharPointerType text, size_t numBytes)
+ {
+ StringHolder* const b = bufferFromText (text);
+
+ if (b == (StringHolder*) &emptyString)
+ {
+ CharPointerType newText (createUninitialisedBytes (numBytes));
+ newText.writeNull();
+ return newText;
+ }
+
+ if (b->allocatedNumBytes >= numBytes && b->refCount.get() <= 0)
+ return text;
+
+ CharPointerType newText (createUninitialisedBytes (jmax (b->allocatedNumBytes, numBytes)));
+ memcpy (newText.getAddress(), text.getAddress(), b->allocatedNumBytes);
+ release (b);
+
+ return newText;
+ }
+
+ static size_t getAllocatedNumBytes (const CharPointerType text) noexcept
+ {
+ return bufferFromText (text)->allocatedNumBytes;
+ }
+
+ //==============================================================================
+ Atomic<int> refCount;
+ size_t allocatedNumBytes;
+ CharType text[1];
+
+private:
+ static inline StringHolder* bufferFromText (const CharPointerType text) noexcept
+ {
+ // (Can't use offsetof() here because of warnings about this not being a POD)
+ return reinterpret_cast<StringHolder*> (reinterpret_cast<char*> (text.getAddress())
+ - (reinterpret_cast<size_t> (reinterpret_cast<StringHolder*> (1)->text) - 1));
+ }
+
+ void compileTimeChecks()
+ {
+ // Let me know if any of these assertions fail on your system!
+ #if JUCE_NATIVE_WCHAR_IS_UTF8
+ static_jassert (sizeof (wchar_t) == 1);
+ #elif JUCE_NATIVE_WCHAR_IS_UTF16
+ static_jassert (sizeof (wchar_t) == 2);
+ #elif JUCE_NATIVE_WCHAR_IS_UTF32
+ static_jassert (sizeof (wchar_t) == 4);
+ #else
+ #error "native wchar_t size is unknown"
+ #endif
+
+ static_jassert (sizeof (EmptyString) == sizeof (StringHolder));
+ }
+};
+
+const String String::empty;
+
+//==============================================================================
+String::String() noexcept : text (&(emptyString.text))
+{
+}
+
+String::~String() noexcept
+{
+ StringHolder::release (text);
+}
+
+String::String (const String& other) noexcept : text (other.text)
+{
+ StringHolder::retain (text);
+}
+
+void String::swapWith (String& other) noexcept
+{
+ std::swap (text, other.text);
+}
+
+void String::clear() noexcept
+{
+ StringHolder::release (text);
+ text = &(emptyString.text);
+}
+
+String& String::operator= (const String& other) noexcept
+{
+ StringHolder::retain (other.text);
+ StringHolder::release (text.atomicSwap (other.text));
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+String::String (String&& other) noexcept : text (other.text)
+{
+ other.text = &(emptyString.text);
+}
+
+String& String::operator= (String&& other) noexcept
+{
+ std::swap (text, other.text);
+ return *this;
+}
+#endif
+
+inline String::PreallocationBytes::PreallocationBytes (const size_t num) noexcept : numBytes (num) {}
+
+String::String (const PreallocationBytes& preallocationSize)
+ : text (StringHolder::createUninitialisedBytes (preallocationSize.numBytes + sizeof (CharPointerType::CharType)))
+{
+}
+
+void String::preallocateBytes (const size_t numBytesNeeded)
+{
+ text = StringHolder::makeUniqueWithByteSize (text, numBytesNeeded + sizeof (CharPointerType::CharType));
+}
+
+int String::getReferenceCount() const noexcept
+{
+ return StringHolder::getReferenceCount (text);
+}
+
+//==============================================================================
+String::String (const char* const t)
+ : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t)))
+{
+ /* If you get an assertion here, then you're trying to create a string from 8-bit data
+ that contains values greater than 127. These can NOT be correctly converted to unicode
+ because there's no way for the String class to know what encoding was used to
+ create them. The source data could be UTF-8, ASCII or one of many local code-pages.
+
+ To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
+ string to the String class - so for example if your source data is actually UTF-8,
+ you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
+ correctly convert the multi-byte characters to unicode. It's *highly* recommended that
+ you use UTF-8 with escape characters in your source code to represent extended characters,
+ because there's no other way to represent these strings in a way that isn't dependent on
+ the compiler, source code editor and platform.
+
+ Note that the Introjucer has a handy string literal generator utility that will convert
+ any unicode string to a valid C++ string literal, creating ascii escape sequences that will
+ work in any compiler.
+ */
+ jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max()));
+}
+
+String::String (const char* const t, const size_t maxChars)
+ : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t), maxChars))
+{
+ /* If you get an assertion here, then you're trying to create a string from 8-bit data
+ that contains values greater than 127. These can NOT be correctly converted to unicode
+ because there's no way for the String class to know what encoding was used to
+ create them. The source data could be UTF-8, ASCII or one of many local code-pages.
+
+ To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
+ string to the String class - so for example if your source data is actually UTF-8,
+ you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
+ correctly convert the multi-byte characters to unicode. It's *highly* recommended that
+ you use UTF-8 with escape characters in your source code to represent extended characters,
+ because there's no other way to represent these strings in a way that isn't dependent on
+ the compiler, source code editor and platform.
+
+ Note that the Introjucer has a handy string literal generator utility that will convert
+ any unicode string to a valid C++ string literal, creating ascii escape sequences that will
+ work in any compiler.
+ */
+ jassert (t == nullptr || CharPointer_ASCII::isValidString (t, (int) maxChars));
+}
+
+String::String (const wchar_t* const t) : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t))) {}
+String::String (const CharPointer_UTF8 t) : text (StringHolder::createFromCharPointer (t)) {}
+String::String (const CharPointer_UTF16 t) : text (StringHolder::createFromCharPointer (t)) {}
+String::String (const CharPointer_UTF32 t) : text (StringHolder::createFromCharPointer (t)) {}
+String::String (const CharPointer_ASCII t) : text (StringHolder::createFromCharPointer (t)) {}
+
+String::String (const CharPointer_UTF8 t, const size_t maxChars) : text (StringHolder::createFromCharPointer (t, maxChars)) {}
+String::String (const CharPointer_UTF16 t, const size_t maxChars) : text (StringHolder::createFromCharPointer (t, maxChars)) {}
+String::String (const CharPointer_UTF32 t, const size_t maxChars) : text (StringHolder::createFromCharPointer (t, maxChars)) {}
+String::String (const wchar_t* const t, size_t maxChars) : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t), maxChars)) {}
+
+String::String (const CharPointer_UTF8 start, const CharPointer_UTF8 end) : text (StringHolder::createFromCharPointer (start, end)) {}
+String::String (const CharPointer_UTF16 start, const CharPointer_UTF16 end) : text (StringHolder::createFromCharPointer (start, end)) {}
+String::String (const CharPointer_UTF32 start, const CharPointer_UTF32 end) : text (StringHolder::createFromCharPointer (start, end)) {}
+
+String::String (const std::string& s) : text (StringHolder::createFromFixedLength (s.data(), s.size())) {}
+
+String String::charToString (const juce_wchar character)
+{
+ String result (PreallocationBytes (CharPointerType::getBytesRequiredFor (character)));
+ CharPointerType t (result.text);
+ t.write (character);
+ t.writeNull();
+ return result;
+}
+
+//==============================================================================
+namespace NumberToStringConverters
+{
+ enum
+ {
+ charsNeededForInt = 32,
+ charsNeededForDouble = 48
+ };
+
+ template <typename Type>
+ static char* printDigits (char* t, Type v) noexcept
+ {
+ *--t = 0;
+
+ do
+ {
+ *--t = '0' + (char) (v % 10);
+ v /= 10;
+
+ } while (v > 0);
+
+ return t;
+ }
+
+ // pass in a pointer to the END of a buffer..
+ static char* numberToString (char* t, const int64 n) noexcept
+ {
+ if (n >= 0)
+ return printDigits (t, static_cast<uint64> (n));
+
+ // NB: this needs to be careful not to call -std::numeric_limits<int64>::min(),
+ // which has undefined behaviour
+ t = printDigits (t, static_cast<uint64> (-(n + 1)) + 1);
+ *--t = '-';
+ return t;
+ }
+
+ static char* numberToString (char* t, uint64 v) noexcept
+ {
+ return printDigits (t, v);
+ }
+
+ static char* numberToString (char* t, const int n) noexcept
+ {
+ if (n >= 0)
+ return printDigits (t, static_cast<unsigned int> (n));
+
+ // NB: this needs to be careful not to call -std::numeric_limits<int>::min(),
+ // which has undefined behaviour
+ t = printDigits (t, static_cast<unsigned int> (-(n + 1)) + 1);
+ *--t = '-';
+ return t;
+ }
+
+ static char* numberToString (char* t, unsigned int v) noexcept
+ {
+ return printDigits (t, v);
+ }
+
+ struct StackArrayStream : public std::basic_streambuf<char, std::char_traits<char> >
+ {
+ explicit StackArrayStream (char* d)
+ {
+ static const std::locale classicLocale (std::locale::classic());
+ imbue (classicLocale);
+ setp (d, d + charsNeededForDouble);
+ }
+
+ size_t writeDouble (double n, int numDecPlaces)
+ {
+ {
+ std::ostream o (this);
+
+ if (numDecPlaces > 0)
+ o.precision ((std::streamsize) numDecPlaces);
+
+ o << n;
+ }
+
+ return (size_t) (pptr() - pbase());
+ }
+ };
+
+ static char* doubleToString (char* buffer, const int numChars, double n, int numDecPlaces, size_t& len) noexcept
+ {
+ if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20)
+ {
+ char* const end = buffer + numChars;
+ char* t = end;
+ int64 v = (int64) (pow (10.0, numDecPlaces) * std::abs (n) + 0.5);
+ *--t = (char) 0;
+
+ while (numDecPlaces >= 0 || v > 0)
+ {
+ if (numDecPlaces == 0)
+ *--t = '.';
+
+ *--t = (char) ('0' + (v % 10));
+
+ v /= 10;
+ --numDecPlaces;
+ }
+
+ if (n < 0)
+ *--t = '-';
+
+ len = (size_t) (end - t - 1);
+ return t;
+ }
+
+ StackArrayStream strm (buffer);
+ len = strm.writeDouble (n, numDecPlaces);
+ jassert (len <= charsNeededForDouble);
+ return buffer;
+ }
+
+ template <typename IntegerType>
+ static String::CharPointerType createFromInteger (const IntegerType number)
+ {
+ char buffer [charsNeededForInt];
+ char* const end = buffer + numElementsInArray (buffer);
+ char* const start = numberToString (end, number);
+ return StringHolder::createFromFixedLength (start, (size_t) (end - start - 1));
+ }
+
+ static String::CharPointerType createFromDouble (const double number, const int numberOfDecimalPlaces)
+ {
+ char buffer [charsNeededForDouble];
+ size_t len;
+ char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len);
+ return StringHolder::createFromFixedLength (start, len);
+ }
+}
+
+//==============================================================================
+String::String (const int number) : text (NumberToStringConverters::createFromInteger (number)) {}
+String::String (const unsigned int number) : text (NumberToStringConverters::createFromInteger (number)) {}
+String::String (const short number) : text (NumberToStringConverters::createFromInteger ((int) number)) {}
+String::String (const unsigned short number) : text (NumberToStringConverters::createFromInteger ((unsigned int) number)) {}
+String::String (const int64 number) : text (NumberToStringConverters::createFromInteger (number)) {}
+String::String (const uint64 number) : text (NumberToStringConverters::createFromInteger (number)) {}
+
+String::String (const float number) : text (NumberToStringConverters::createFromDouble ((double) number, 0)) {}
+String::String (const double number) : text (NumberToStringConverters::createFromDouble (number, 0)) {}
+String::String (const float number, const int numberOfDecimalPlaces) : text (NumberToStringConverters::createFromDouble ((double) number, numberOfDecimalPlaces)) {}
+String::String (const double number, const int numberOfDecimalPlaces) : text (NumberToStringConverters::createFromDouble (number, numberOfDecimalPlaces)) {}
+
+//==============================================================================
+int String::length() const noexcept
+{
+ return (int) text.length();
+}
+
+static size_t findByteOffsetOfEnd (String::CharPointerType text) noexcept
+{
+ return (size_t) (((char*) text.findTerminatingNull().getAddress()) - (char*) text.getAddress());
+}
+
+size_t String::getByteOffsetOfEnd() const noexcept
+{
+ return findByteOffsetOfEnd (text);
+}
+
+juce_wchar String::operator[] (int index) const noexcept
+{
+ jassert (index == 0 || (index > 0 && index <= (int) text.lengthUpTo ((size_t) index + 1)));
+ return text [index];
+}
+
+template <typename Type>
+struct HashGenerator
+{
+ template <typename CharPointer>
+ static Type calculate (CharPointer t) noexcept
+ {
+ Type result = Type();
+
+ while (! t.isEmpty())
+ result = ((Type) multiplier) * result + (Type) t.getAndAdvance();
+
+ return result;
+ }
+
+ enum { multiplier = sizeof (Type) > 4 ? 101 : 31 };
+};
+
+int String::hashCode() const noexcept { return HashGenerator<int> ::calculate (text); }
+int64 String::hashCode64() const noexcept { return HashGenerator<int64> ::calculate (text); }
+std::size_t String::hash() const noexcept { return HashGenerator<std::size_t>::calculate (text); }
+
+//==============================================================================
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const String& s2) noexcept { return s1.compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const String& s2) noexcept { return s1.compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const char* s2) noexcept { return s1.compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const char* s2) noexcept { return s1.compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const wchar_t* s2) noexcept { return s1.compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const wchar_t* s2) noexcept { return s1.compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; }
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; }
+JUCE_API bool JUCE_CALLTYPE operator> (const String& s1, const String& s2) noexcept { return s1.compare (s2) > 0; }
+JUCE_API bool JUCE_CALLTYPE operator< (const String& s1, const String& s2) noexcept { return s1.compare (s2) < 0; }
+JUCE_API bool JUCE_CALLTYPE operator>= (const String& s1, const String& s2) noexcept { return s1.compare (s2) >= 0; }
+JUCE_API bool JUCE_CALLTYPE operator<= (const String& s1, const String& s2) noexcept { return s1.compare (s2) <= 0; }
+
+bool String::equalsIgnoreCase (const wchar_t* const t) const noexcept
+{
+ return t != nullptr ? text.compareIgnoreCase (castToCharPointer_wchar_t (t)) == 0
+ : isEmpty();
+}
+
+bool String::equalsIgnoreCase (const char* const t) const noexcept
+{
+ return t != nullptr ? text.compareIgnoreCase (CharPointer_UTF8 (t)) == 0
+ : isEmpty();
+}
+
+bool String::equalsIgnoreCase (StringRef t) const noexcept
+{
+ return text.compareIgnoreCase (t.text) == 0;
+}
+
+bool String::equalsIgnoreCase (const String& other) const noexcept
+{
+ return text == other.text
+ || text.compareIgnoreCase (other.text) == 0;
+}
+
+int String::compare (const String& other) const noexcept { return (text == other.text) ? 0 : text.compare (other.text); }
+int String::compare (const char* const other) const noexcept { return text.compare (CharPointer_UTF8 (other)); }
+int String::compare (const wchar_t* const other) const noexcept { return text.compare (castToCharPointer_wchar_t (other)); }
+int String::compareIgnoreCase (const String& other) const noexcept { return (text == other.text) ? 0 : text.compareIgnoreCase (other.text); }
+
+static int stringCompareRight (String::CharPointerType s1, String::CharPointerType s2) noexcept
+{
+ for (int bias = 0;;)
+ {
+ const juce_wchar c1 = s1.getAndAdvance();
+ const bool isDigit1 = CharacterFunctions::isDigit (c1);
+
+ const juce_wchar c2 = s2.getAndAdvance();
+ const bool isDigit2 = CharacterFunctions::isDigit (c2);
+
+ if (! (isDigit1 || isDigit2)) return bias;
+ if (! isDigit1) return -1;
+ if (! isDigit2) return 1;
+
+ if (c1 != c2 && bias == 0)
+ bias = c1 < c2 ? -1 : 1;
+
+ jassert (c1 != 0 && c2 != 0);
+ }
+}
+
+static int stringCompareLeft (String::CharPointerType s1, String::CharPointerType s2) noexcept
+{
+ for (;;)
+ {
+ const juce_wchar c1 = s1.getAndAdvance();
+ const bool isDigit1 = CharacterFunctions::isDigit (c1);
+
+ const juce_wchar c2 = s2.getAndAdvance();
+ const bool isDigit2 = CharacterFunctions::isDigit (c2);
+
+ if (! (isDigit1 || isDigit2)) return 0;
+ if (! isDigit1) return -1;
+ if (! isDigit2) return 1;
+ if (c1 < c2) return -1;
+ if (c1 > c2) return 1;
+ }
+}
+
+static int naturalStringCompare (String::CharPointerType s1, String::CharPointerType s2) noexcept
+{
+ bool firstLoop = true;
+
+ for (;;)
+ {
+ const bool hasSpace1 = s1.isWhitespace();
+ const bool hasSpace2 = s2.isWhitespace();
+
+ if ((! firstLoop) && (hasSpace1 ^ hasSpace2))
+ return hasSpace2 ? 1 : -1;
+
+ firstLoop = false;
+
+ if (hasSpace1) s1 = s1.findEndOfWhitespace();
+ if (hasSpace2) s2 = s2.findEndOfWhitespace();
+
+ if (s1.isDigit() && s2.isDigit())
+ {
+ const int result = (*s1 == '0' || *s2 == '0') ? stringCompareLeft (s1, s2)
+ : stringCompareRight (s1, s2);
+
+ if (result != 0)
+ return result;
+ }
+
+ juce_wchar c1 = s1.getAndAdvance();
+ juce_wchar c2 = s2.getAndAdvance();
+
+ if (c1 != c2)
+ {
+ c1 = CharacterFunctions::toUpperCase (c1);
+ c2 = CharacterFunctions::toUpperCase (c2);
+ }
+
+ if (c1 == c2)
+ {
+ if (c1 == 0)
+ return 0;
+ }
+ else
+ {
+ const bool isAlphaNum1 = CharacterFunctions::isLetterOrDigit (c1);
+ const bool isAlphaNum2 = CharacterFunctions::isLetterOrDigit (c2);
+
+ if (isAlphaNum2 && ! isAlphaNum1) return -1;
+ if (isAlphaNum1 && ! isAlphaNum2) return 1;
+
+ return c1 < c2 ? -1 : 1;
+ }
+
+ jassert (c1 != 0 && c2 != 0);
+ }
+}
+
+int String::compareNatural (StringRef other) const noexcept
+{
+ return naturalStringCompare (getCharPointer(), other.text);
+}
+
+//==============================================================================
+void String::append (const String& textToAppend, size_t maxCharsToTake)
+{
+ appendCharPointer (textToAppend.text, maxCharsToTake);
+}
+
+void String::appendCharPointer (const CharPointerType textToAppend)
+{
+ appendCharPointer (textToAppend, textToAppend.findTerminatingNull());
+}
+
+void String::appendCharPointer (const CharPointerType startOfTextToAppend,
+ const CharPointerType endOfTextToAppend)
+{
+ jassert (startOfTextToAppend.getAddress() != nullptr && endOfTextToAppend.getAddress() != nullptr);
+
+ const int extraBytesNeeded = getAddressDifference (endOfTextToAppend.getAddress(),
+ startOfTextToAppend.getAddress());
+ jassert (extraBytesNeeded >= 0);
+
+ if (extraBytesNeeded > 0)
+ {
+ const size_t byteOffsetOfNull = getByteOffsetOfEnd();
+ preallocateBytes (byteOffsetOfNull + (size_t) extraBytesNeeded);
+
+ CharPointerType::CharType* const newStringStart = addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull);
+ memcpy (newStringStart, startOfTextToAppend.getAddress(), (size_t) extraBytesNeeded);
+ CharPointerType (addBytesToPointer (newStringStart, extraBytesNeeded)).writeNull();
+ }
+}
+
+String& String::operator+= (const wchar_t* const t)
+{
+ appendCharPointer (castToCharPointer_wchar_t (t));
+ return *this;
+}
+
+String& String::operator+= (const char* const t)
+{
+ appendCharPointer (CharPointer_UTF8 (t)); // (using UTF8 here triggers a faster code-path than ascii)
+ return *this;
+}
+
+String& String::operator+= (const String& other)
+{
+ if (isEmpty())
+ return operator= (other);
+
+ appendCharPointer (other.text);
+ return *this;
+}
+
+String& String::operator+= (const char ch)
+{
+ const char asString[] = { ch, 0 };
+ return operator+= (asString);
+}
+
+String& String::operator+= (const wchar_t ch)
+{
+ const wchar_t asString[] = { ch, 0 };
+ return operator+= (asString);
+}
+
+#if ! JUCE_NATIVE_WCHAR_IS_UTF32
+String& String::operator+= (const juce_wchar ch)
+{
+ const juce_wchar asString[] = { ch, 0 };
+ appendCharPointer (CharPointer_UTF32 (asString));
+ return *this;
+}
+#endif
+
+String& String::operator+= (const int number)
+{
+ char buffer [16];
+ char* end = buffer + numElementsInArray (buffer);
+ char* start = NumberToStringConverters::numberToString (end, number);
+
+ #if (JUCE_STRING_UTF_TYPE == 8)
+ appendCharPointer (CharPointerType (start), CharPointerType (end));
+ #else
+ appendCharPointer (CharPointer_ASCII (start), CharPointer_ASCII (end));
+ #endif
+ return *this;
+}
+
+String& String::operator+= (int64 number)
+{
+ char buffer [32];
+ char* end = buffer + numElementsInArray (buffer);
+ char* start = NumberToStringConverters::numberToString (end, number);
+
+ #if (JUCE_STRING_UTF_TYPE == 8)
+ appendCharPointer (CharPointerType (start), CharPointerType (end));
+ #else
+ appendCharPointer (CharPointer_ASCII (start), CharPointer_ASCII (end));
+ #endif
+ return *this;
+}
+
+//==============================================================================
+JUCE_API String JUCE_CALLTYPE operator+ (const char* const s1, const String& s2) { String s (s1); return s += s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (const wchar_t* const s1, const String& s2) { String s (s1); return s += s2; }
+
+JUCE_API String JUCE_CALLTYPE operator+ (const char s1, const String& s2) { return String::charToString ((juce_wchar) (uint8) s1) + s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (const wchar_t s1, const String& s2) { return String::charToString (s1) + s2; }
+
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const String& s2) { return s1 += s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char* const s2) { return s1 += s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const wchar_t* s2) { return s1 += s2; }
+
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char s2) { return s1 += s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const wchar_t s2) { return s1 += s2; }
+
+#if ! JUCE_NATIVE_WCHAR_IS_UTF32
+JUCE_API String JUCE_CALLTYPE operator+ (const juce_wchar s1, const String& s2) { return String::charToString (s1) + s2; }
+JUCE_API String JUCE_CALLTYPE operator+ (String s1, const juce_wchar s2) { return s1 += s2; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const juce_wchar s2) { return s1 += s2; }
+#endif
+
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const char s2) { return s1 += s2; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const wchar_t s2) { return s1 += s2; }
+
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const char* const s2) { return s1 += s2; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const wchar_t* const s2) { return s1 += s2; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const String& s2) { return s1 += s2; }
+
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const int number) { return s1 += number; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const short number) { return s1 += (int) number; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const long number) { return s1 += (int) number; }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const int64 number) { return s1 += String (number); }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const float number) { return s1 += String (number); }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const double number) { return s1 += String (number); }
+JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const uint64 number) { return s1 += String (number); }
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text)
+{
+ return operator<< (stream, StringRef (text));
+}
+
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, StringRef text)
+{
+ const size_t numBytes = CharPointer_UTF8::getBytesRequiredFor (text.text);
+
+ #if (JUCE_STRING_UTF_TYPE == 8)
+ stream.write (text.text.getAddress(), numBytes);
+ #else
+ // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind
+ // if lots of large, persistent strings were to be written to streams).
+ HeapBlock<char> temp (numBytes + 1);
+ CharPointer_UTF8 (temp).writeAll (text.text);
+ stream.write (temp, numBytes);
+ #endif
+
+ return stream;
+}
+
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&)
+{
+ return string1 += NewLine::getDefault();
+}
+
+//==============================================================================
+int String::indexOfChar (const juce_wchar character) const noexcept
+{
+ return text.indexOf (character);
+}
+
+int String::indexOfChar (const int startIndex, const juce_wchar character) const noexcept
+{
+ CharPointerType t (text);
+
+ for (int i = 0; ! t.isEmpty(); ++i)
+ {
+ if (i >= startIndex)
+ {
+ if (t.getAndAdvance() == character)
+ return i;
+ }
+ else
+ {
+ ++t;
+ }
+ }
+
+ return -1;
+}
+
+int String::lastIndexOfChar (const juce_wchar character) const noexcept
+{
+ CharPointerType t (text);
+ int last = -1;
+
+ for (int i = 0; ! t.isEmpty(); ++i)
+ if (t.getAndAdvance() == character)
+ last = i;
+
+ return last;
+}
+
+int String::indexOfAnyOf (StringRef charactersToLookFor, const int startIndex, const bool ignoreCase) const noexcept
+{
+ CharPointerType t (text);
+
+ for (int i = 0; ! t.isEmpty(); ++i)
+ {
+ if (i >= startIndex)
+ {
+ if (charactersToLookFor.text.indexOf (t.getAndAdvance(), ignoreCase) >= 0)
+ return i;
+ }
+ else
+ {
+ ++t;
+ }
+ }
+
+ return -1;
+}
+
+int String::indexOf (StringRef other) const noexcept
+{
+ return other.isEmpty() ? 0 : text.indexOf (other.text);
+}
+
+int String::indexOfIgnoreCase (StringRef other) const noexcept
+{
+ return other.isEmpty() ? 0 : CharacterFunctions::indexOfIgnoreCase (text, other.text);
+}
+
+int String::indexOf (const int startIndex, StringRef other) const noexcept
+{
+ if (other.isEmpty())
+ return -1;
+
+ CharPointerType t (text);
+
+ for (int i = startIndex; --i >= 0;)
+ {
+ if (t.isEmpty())
+ return -1;
+
+ ++t;
+ }
+
+ int found = t.indexOf (other.text);
+ if (found >= 0)
+ found += startIndex;
+ return found;
+}
+
+int String::indexOfIgnoreCase (const int startIndex, StringRef other) const noexcept
+{
+ if (other.isEmpty())
+ return -1;
+
+ CharPointerType t (text);
+
+ for (int i = startIndex; --i >= 0;)
+ {
+ if (t.isEmpty())
+ return -1;
+
+ ++t;
+ }
+
+ int found = CharacterFunctions::indexOfIgnoreCase (t, other.text);
+ if (found >= 0)
+ found += startIndex;
+ return found;
+}
+
+int String::lastIndexOf (StringRef other) const noexcept
+{
+ if (other.isNotEmpty())
+ {
+ const int len = other.length();
+ int i = length() - len;
+
+ if (i >= 0)
+ {
+ for (CharPointerType n (text + i); i >= 0; --i)
+ {
+ if (n.compareUpTo (other.text, len) == 0)
+ return i;
+
+ --n;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int String::lastIndexOfIgnoreCase (StringRef other) const noexcept
+{
+ if (other.isNotEmpty())
+ {
+ const int len = other.length();
+ int i = length() - len;
+
+ if (i >= 0)
+ {
+ for (CharPointerType n (text + i); i >= 0; --i)
+ {
+ if (n.compareIgnoreCaseUpTo (other.text, len) == 0)
+ return i;
+
+ --n;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int String::lastIndexOfAnyOf (StringRef charactersToLookFor, const bool ignoreCase) const noexcept
+{
+ CharPointerType t (text);
+ int last = -1;
+
+ for (int i = 0; ! t.isEmpty(); ++i)
+ if (charactersToLookFor.text.indexOf (t.getAndAdvance(), ignoreCase) >= 0)
+ last = i;
+
+ return last;
+}
+
+bool String::contains (StringRef other) const noexcept
+{
+ return indexOf (other) >= 0;
+}
+
+bool String::containsChar (const juce_wchar character) const noexcept
+{
+ return text.indexOf (character) >= 0;
+}
+
+bool String::containsIgnoreCase (StringRef t) const noexcept
+{
+ return indexOfIgnoreCase (t) >= 0;
+}
+
+int String::indexOfWholeWord (StringRef word) const noexcept
+{
+ if (word.isNotEmpty())
+ {
+ CharPointerType t (text);
+ const int wordLen = word.length();
+ const int end = (int) t.length() - wordLen;
+
+ for (int i = 0; i <= end; ++i)
+ {
+ if (t.compareUpTo (word.text, wordLen) == 0
+ && (i == 0 || ! (t - 1).isLetterOrDigit())
+ && ! (t + wordLen).isLetterOrDigit())
+ return i;
+
+ ++t;
+ }
+ }
+
+ return -1;
+}
+
+int String::indexOfWholeWordIgnoreCase (StringRef word) const noexcept
+{
+ if (word.isNotEmpty())
+ {
+ CharPointerType t (text);
+ const int wordLen = word.length();
+ const int end = (int) t.length() - wordLen;
+
+ for (int i = 0; i <= end; ++i)
+ {
+ if (t.compareIgnoreCaseUpTo (word.text, wordLen) == 0
+ && (i == 0 || ! (t - 1).isLetterOrDigit())
+ && ! (t + wordLen).isLetterOrDigit())
+ return i;
+
+ ++t;
+ }
+ }
+
+ return -1;
+}
+
+bool String::containsWholeWord (StringRef wordToLookFor) const noexcept
+{
+ return indexOfWholeWord (wordToLookFor) >= 0;
+}
+
+bool String::containsWholeWordIgnoreCase (StringRef wordToLookFor) const noexcept
+{
+ return indexOfWholeWordIgnoreCase (wordToLookFor) >= 0;
+}
+
+//==============================================================================
+template <typename CharPointer>
+struct WildCardMatcher
+{
+ static bool matches (CharPointer wildcard, CharPointer test, const bool ignoreCase) noexcept
+ {
+ for (;;)
+ {
+ const juce_wchar wc = wildcard.getAndAdvance();
+
+ if (wc == '*')
+ return wildcard.isEmpty() || matchesAnywhere (wildcard, test, ignoreCase);
+
+ if (! characterMatches (wc, test.getAndAdvance(), ignoreCase))
+ return false;
+
+ if (wc == 0)
+ return true;
+ }
+ }
+
+ static bool characterMatches (const juce_wchar wc, const juce_wchar tc, const bool ignoreCase) noexcept
+ {
+ return (wc == tc) || (wc == '?' && tc != 0)
+ || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (tc));
+ }
+
+ static bool matchesAnywhere (const CharPointer wildcard, CharPointer test, const bool ignoreCase) noexcept
+ {
+ for (; ! test.isEmpty(); ++test)
+ if (matches (wildcard, test, ignoreCase))
+ return true;
+
+ return false;
+ }
+};
+
+bool String::matchesWildcard (StringRef wildcard, const bool ignoreCase) const noexcept
+{
+ return WildCardMatcher<CharPointerType>::matches (wildcard.text, text, ignoreCase);
+}
+
+//==============================================================================
+String String::repeatedString (StringRef stringToRepeat, int numberOfTimesToRepeat)
+{
+ if (numberOfTimesToRepeat <= 0)
+ return String();
+
+ String result (PreallocationBytes (findByteOffsetOfEnd (stringToRepeat) * (size_t) numberOfTimesToRepeat));
+ CharPointerType n (result.text);
+
+ while (--numberOfTimesToRepeat >= 0)
+ n.writeAll (stringToRepeat.text);
+
+ return result;
+}
+
+String String::paddedLeft (const juce_wchar padCharacter, int minimumLength) const
+{
+ jassert (padCharacter != 0);
+
+ int extraChars = minimumLength;
+ CharPointerType end (text);
+
+ while (! end.isEmpty())
+ {
+ --extraChars;
+ ++end;
+ }
+
+ if (extraChars <= 0 || padCharacter == 0)
+ return *this;
+
+ const size_t currentByteSize = (size_t) (((char*) end.getAddress()) - (char*) text.getAddress());
+ String result (PreallocationBytes (currentByteSize + (size_t) extraChars * CharPointerType::getBytesRequiredFor (padCharacter)));
+ CharPointerType n (result.text);
+
+ while (--extraChars >= 0)
+ n.write (padCharacter);
+
+ n.writeAll (text);
+ return result;
+}
+
+String String::paddedRight (const juce_wchar padCharacter, int minimumLength) const
+{
+ jassert (padCharacter != 0);
+
+ int extraChars = minimumLength;
+ CharPointerType end (text);
+
+ while (! end.isEmpty())
+ {
+ --extraChars;
+ ++end;
+ }
+
+ if (extraChars <= 0 || padCharacter == 0)
+ return *this;
+
+ const size_t currentByteSize = (size_t) (((char*) end.getAddress()) - (char*) text.getAddress());
+ String result (PreallocationBytes (currentByteSize + (size_t) extraChars * CharPointerType::getBytesRequiredFor (padCharacter)));
+ CharPointerType n (result.text);
+
+ n.writeAll (text);
+
+ while (--extraChars >= 0)
+ n.write (padCharacter);
+
+ n.writeNull();
+ return result;
+}
+
+//==============================================================================
+String String::replaceSection (int index, int numCharsToReplace, StringRef stringToInsert) const
+{
+ if (index < 0)
+ {
+ // a negative index to replace from?
+ jassertfalse;
+ index = 0;
+ }
+
+ if (numCharsToReplace < 0)
+ {
+ // replacing a negative number of characters?
+ numCharsToReplace = 0;
+ jassertfalse;
+ }
+
+ CharPointerType insertPoint (text);
+
+ for (int i = 0; i < index; ++i)
+ {
+ if (insertPoint.isEmpty())
+ {
+ // replacing beyond the end of the string?
+ jassertfalse;
+ return *this + stringToInsert;
+ }
+
+ ++insertPoint;
+ }
+
+ CharPointerType startOfRemainder (insertPoint);
+
+ for (int i = 0; i < numCharsToReplace && ! startOfRemainder.isEmpty(); ++i)
+ ++startOfRemainder;
+
+ if (insertPoint == text && startOfRemainder.isEmpty())
+ return stringToInsert.text;
+
+ const size_t initialBytes = (size_t) (((char*) insertPoint.getAddress()) - (char*) text.getAddress());
+ const size_t newStringBytes = findByteOffsetOfEnd (stringToInsert);
+ const size_t remainderBytes = (size_t) (((char*) startOfRemainder.findTerminatingNull().getAddress()) - (char*) startOfRemainder.getAddress());
+
+ const size_t newTotalBytes = initialBytes + newStringBytes + remainderBytes;
+ if (newTotalBytes <= 0)
+ return String();
+
+ String result (PreallocationBytes ((size_t) newTotalBytes));
+
+ char* dest = (char*) result.text.getAddress();
+ memcpy (dest, text.getAddress(), initialBytes);
+ dest += initialBytes;
+ memcpy (dest, stringToInsert.text.getAddress(), newStringBytes);
+ dest += newStringBytes;
+ memcpy (dest, startOfRemainder.getAddress(), remainderBytes);
+ dest += remainderBytes;
+ CharPointerType ((CharPointerType::CharType*) dest).writeNull();
+
+ return result;
+}
+
+String String::replace (StringRef stringToReplace, StringRef stringToInsert, const bool ignoreCase) const
+{
+ const int stringToReplaceLen = stringToReplace.length();
+ const int stringToInsertLen = stringToInsert.length();
+
+ int i = 0;
+ String result (*this);
+
+ while ((i = (ignoreCase ? result.indexOfIgnoreCase (i, stringToReplace)
+ : result.indexOf (i, stringToReplace))) >= 0)
+ {
+ result = result.replaceSection (i, stringToReplaceLen, stringToInsert);
+ i += stringToInsertLen;
+ }
+
+ return result;
+}
+
+class StringCreationHelper
+{
+public:
+ StringCreationHelper (const size_t initialBytes)
+ : source (nullptr), dest (nullptr), allocatedBytes (initialBytes), bytesWritten (0)
+ {
+ result.preallocateBytes (allocatedBytes);
+ dest = result.getCharPointer();
+ }
+
+ StringCreationHelper (const String::CharPointerType s)
+ : source (s), dest (nullptr), allocatedBytes (StringHolder::getAllocatedNumBytes (s)), bytesWritten (0)
+ {
+ result.preallocateBytes (allocatedBytes);
+ dest = result.getCharPointer();
+ }
+
+ void write (juce_wchar c)
+ {
+ bytesWritten += String::CharPointerType::getBytesRequiredFor (c);
+
+ if (bytesWritten > allocatedBytes)
+ {
+ allocatedBytes += jmax ((size_t) 8, allocatedBytes / 16);
+ const size_t destOffset = (size_t) (((char*) dest.getAddress()) - (char*) result.getCharPointer().getAddress());
+ result.preallocateBytes (allocatedBytes);
+ dest = addBytesToPointer (result.getCharPointer().getAddress(), (int) destOffset);
+ }
+
+ dest.write (c);
+ }
+
+ String result;
+ String::CharPointerType source;
+
+private:
+ String::CharPointerType dest;
+ size_t allocatedBytes, bytesWritten;
+};
+
+String String::replaceCharacter (const juce_wchar charToReplace, const juce_wchar charToInsert) const
+{
+ if (! containsChar (charToReplace))
+ return *this;
+
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ juce_wchar c = builder.source.getAndAdvance();
+
+ if (c == charToReplace)
+ c = charToInsert;
+
+ builder.write (c);
+
+ if (c == 0)
+ break;
+ }
+
+ return builder.result;
+}
+
+String String::replaceCharacters (StringRef charactersToReplace, StringRef charactersToInsertInstead) const
+{
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ juce_wchar c = builder.source.getAndAdvance();
+
+ const int index = charactersToReplace.text.indexOf (c);
+ if (index >= 0)
+ c = charactersToInsertInstead [index];
+
+ builder.write (c);
+
+ if (c == 0)
+ break;
+ }
+
+ return builder.result;
+}
+
+//==============================================================================
+bool String::startsWith (StringRef other) const noexcept
+{
+ return text.compareUpTo (other.text, other.length()) == 0;
+}
+
+bool String::startsWithIgnoreCase (StringRef other) const noexcept
+{
+ return text.compareIgnoreCaseUpTo (other.text, other.length()) == 0;
+}
+
+bool String::startsWithChar (const juce_wchar character) const noexcept
+{
+ jassert (character != 0); // strings can't contain a null character!
+
+ return *text == character;
+}
+
+bool String::endsWithChar (const juce_wchar character) const noexcept
+{
+ jassert (character != 0); // strings can't contain a null character!
+
+ if (text.isEmpty())
+ return false;
+
+ CharPointerType t (text.findTerminatingNull());
+ return *--t == character;
+}
+
+bool String::endsWith (StringRef other) const noexcept
+{
+ CharPointerType end (text.findTerminatingNull());
+ CharPointerType otherEnd (other.text.findTerminatingNull());
+
+ while (end > text && otherEnd > other.text)
+ {
+ --end;
+ --otherEnd;
+
+ if (*end != *otherEnd)
+ return false;
+ }
+
+ return otherEnd == other.text;
+}
+
+bool String::endsWithIgnoreCase (StringRef other) const noexcept
+{
+ CharPointerType end (text.findTerminatingNull());
+ CharPointerType otherEnd (other.text.findTerminatingNull());
+
+ while (end > text && otherEnd > other.text)
+ {
+ --end;
+ --otherEnd;
+
+ if (end.toLowerCase() != otherEnd.toLowerCase())
+ return false;
+ }
+
+ return otherEnd == other.text;
+}
+
+//==============================================================================
+String String::toUpperCase() const
+{
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ const juce_wchar c = builder.source.toUpperCase();
+ builder.write (c);
+
+ if (c == 0)
+ break;
+
+ ++(builder.source);
+ }
+
+ return builder.result;
+}
+
+String String::toLowerCase() const
+{
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ const juce_wchar c = builder.source.toLowerCase();
+ builder.write (c);
+
+ if (c == 0)
+ break;
+
+ ++(builder.source);
+ }
+
+ return builder.result;
+}
+
+//==============================================================================
+juce_wchar String::getLastCharacter() const noexcept
+{
+ return isEmpty() ? juce_wchar() : text [length() - 1];
+}
+
+String String::substring (int start, const int end) const
+{
+ if (start < 0)
+ start = 0;
+
+ if (end <= start)
+ return String();
+
+ int i = 0;
+ CharPointerType t1 (text);
+
+ while (i < start)
+ {
+ if (t1.isEmpty())
+ return String();
+
+ ++i;
+ ++t1;
+ }
+
+ CharPointerType t2 (t1);
+ while (i < end)
+ {
+ if (t2.isEmpty())
+ {
+ if (start == 0)
+ return *this;
+
+ break;
+ }
+
+ ++i;
+ ++t2;
+ }
+
+ return String (t1, t2);
+}
+
+String String::substring (int start) const
+{
+ if (start <= 0)
+ return *this;
+
+ CharPointerType t (text);
+
+ while (--start >= 0)
+ {
+ if (t.isEmpty())
+ return String();
+
+ ++t;
+ }
+
+ return String (t);
+}
+
+String String::dropLastCharacters (const int numberToDrop) const
+{
+ return String (text, (size_t) jmax (0, length() - numberToDrop));
+}
+
+String String::getLastCharacters (const int numCharacters) const
+{
+ return String (text + jmax (0, length() - jmax (0, numCharacters)));
+}
+
+String String::fromFirstOccurrenceOf (StringRef sub,
+ const bool includeSubString,
+ const bool ignoreCase) const
+{
+ const int i = ignoreCase ? indexOfIgnoreCase (sub)
+ : indexOf (sub);
+ if (i < 0)
+ return String();
+
+ return substring (includeSubString ? i : i + sub.length());
+}
+
+String String::fromLastOccurrenceOf (StringRef sub,
+ const bool includeSubString,
+ const bool ignoreCase) const
+{
+ const int i = ignoreCase ? lastIndexOfIgnoreCase (sub)
+ : lastIndexOf (sub);
+ if (i < 0)
+ return *this;
+
+ return substring (includeSubString ? i : i + sub.length());
+}
+
+String String::upToFirstOccurrenceOf (StringRef sub,
+ const bool includeSubString,
+ const bool ignoreCase) const
+{
+ const int i = ignoreCase ? indexOfIgnoreCase (sub)
+ : indexOf (sub);
+ if (i < 0)
+ return *this;
+
+ return substring (0, includeSubString ? i + sub.length() : i);
+}
+
+String String::upToLastOccurrenceOf (StringRef sub,
+ const bool includeSubString,
+ const bool ignoreCase) const
+{
+ const int i = ignoreCase ? lastIndexOfIgnoreCase (sub)
+ : lastIndexOf (sub);
+ if (i < 0)
+ return *this;
+
+ return substring (0, includeSubString ? i + sub.length() : i);
+}
+
+bool String::isQuotedString() const
+{
+ const String trimmed (trimStart());
+
+ return trimmed[0] == '"'
+ || trimmed[0] == '\'';
+}
+
+String String::unquoted() const
+{
+ const int len = length();
+
+ if (len == 0)
+ return String();
+
+ const juce_wchar lastChar = text [len - 1];
+ const int dropAtStart = (*text == '"' || *text == '\'') ? 1 : 0;
+ const int dropAtEnd = (lastChar == '"' || lastChar == '\'') ? 1 : 0;
+
+ return substring (dropAtStart, len - dropAtEnd);
+}
+
+String String::quoted (const juce_wchar quoteCharacter) const
+{
+ if (isEmpty())
+ return charToString (quoteCharacter) + quoteCharacter;
+
+ String t (*this);
+
+ if (! t.startsWithChar (quoteCharacter))
+ t = charToString (quoteCharacter) + t;
+
+ if (! t.endsWithChar (quoteCharacter))
+ t += quoteCharacter;
+
+ return t;
+}
+
+//==============================================================================
+static String::CharPointerType findTrimmedEnd (const String::CharPointerType start,
+ String::CharPointerType end)
+{
+ while (end > start)
+ {
+ if (! (--end).isWhitespace())
+ {
+ ++end;
+ break;
+ }
+ }
+
+ return end;
+}
+
+String String::trim() const
+{
+ if (isNotEmpty())
+ {
+ CharPointerType start (text.findEndOfWhitespace());
+
+ const CharPointerType end (start.findTerminatingNull());
+ CharPointerType trimmedEnd (findTrimmedEnd (start, end));
+
+ if (trimmedEnd <= start)
+ return String();
+
+ if (text < start || trimmedEnd < end)
+ return String (start, trimmedEnd);
+ }
+
+ return *this;
+}
+
+String String::trimStart() const
+{
+ if (isNotEmpty())
+ {
+ const CharPointerType t (text.findEndOfWhitespace());
+
+ if (t != text)
+ return String (t);
+ }
+
+ return *this;
+}
+
+String String::trimEnd() const
+{
+ if (isNotEmpty())
+ {
+ const CharPointerType end (text.findTerminatingNull());
+ CharPointerType trimmedEnd (findTrimmedEnd (text, end));
+
+ if (trimmedEnd < end)
+ return String (text, trimmedEnd);
+ }
+
+ return *this;
+}
+
+String String::trimCharactersAtStart (StringRef charactersToTrim) const
+{
+ CharPointerType t (text);
+
+ while (charactersToTrim.text.indexOf (*t) >= 0)
+ ++t;
+
+ return t == text ? *this : String (t);
+}
+
+String String::trimCharactersAtEnd (StringRef charactersToTrim) const
+{
+ if (isNotEmpty())
+ {
+ const CharPointerType end (text.findTerminatingNull());
+ CharPointerType trimmedEnd (end);
+
+ while (trimmedEnd > text)
+ {
+ if (charactersToTrim.text.indexOf (*--trimmedEnd) < 0)
+ {
+ ++trimmedEnd;
+ break;
+ }
+ }
+
+ if (trimmedEnd < end)
+ return String (text, trimmedEnd);
+ }
+
+ return *this;
+}
+
+//==============================================================================
+String String::retainCharacters (StringRef charactersToRetain) const
+{
+ if (isEmpty())
+ return String();
+
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ juce_wchar c = builder.source.getAndAdvance();
+
+ if (charactersToRetain.text.indexOf (c) >= 0)
+ builder.write (c);
+
+ if (c == 0)
+ break;
+ }
+
+ builder.write (0);
+ return builder.result;
+}
+
+String String::removeCharacters (StringRef charactersToRemove) const
+{
+ if (isEmpty())
+ return String();
+
+ StringCreationHelper builder (text);
+
+ for (;;)
+ {
+ juce_wchar c = builder.source.getAndAdvance();
+
+ if (charactersToRemove.text.indexOf (c) < 0)
+ builder.write (c);
+
+ if (c == 0)
+ break;
+ }
+
+ return builder.result;
+}
+
+String String::initialSectionContainingOnly (StringRef permittedCharacters) const
+{
+ for (CharPointerType t (text); ! t.isEmpty(); ++t)
+ if (permittedCharacters.text.indexOf (*t) < 0)
+ return String (text, t);
+
+ return *this;
+}
+
+String String::initialSectionNotContaining (StringRef charactersToStopAt) const
+{
+ for (CharPointerType t (text); ! t.isEmpty(); ++t)
+ if (charactersToStopAt.text.indexOf (*t) >= 0)
+ return String (text, t);
+
+ return *this;
+}
+
+bool String::containsOnly (StringRef chars) const noexcept
+{
+ for (CharPointerType t (text); ! t.isEmpty();)
+ if (chars.text.indexOf (t.getAndAdvance()) < 0)
+ return false;
+
+ return true;
+}
+
+bool String::containsAnyOf (StringRef chars) const noexcept
+{
+ for (CharPointerType t (text); ! t.isEmpty();)
+ if (chars.text.indexOf (t.getAndAdvance()) >= 0)
+ return true;
+
+ return false;
+}
+
+bool String::containsNonWhitespaceChars() const noexcept
+{
+ for (CharPointerType t (text); ! t.isEmpty(); ++t)
+ if (! t.isWhitespace())
+ return true;
+
+ return false;
+}
+
+// Note! The format parameter here MUST NOT be a reference, otherwise MS's va_start macro fails to work (but still compiles).
+String String::formatted (const String pf, ... )
+{
+ size_t bufferSize = 256;
+
+ for (;;)
+ {
+ va_list args;
+ va_start (args, pf);
+
+ #if JUCE_WINDOWS
+ HeapBlock<wchar_t> temp (bufferSize);
+ const int num = (int) _vsnwprintf (temp.getData(), bufferSize - 1, pf.toWideCharPointer(), args);
+ #elif JUCE_ANDROID
+ HeapBlock<char> temp (bufferSize);
+ const int num = (int) vsnprintf (temp.getData(), bufferSize - 1, pf.toUTF8(), args);
+ #else
+ HeapBlock<wchar_t> temp (bufferSize);
+ const int num = (int) vswprintf (temp.getData(), bufferSize - 1, pf.toWideCharPointer(), args);
+ #endif
+
+ va_end (args);
+
+ if (num > 0)
+ return String (temp);
+
+ bufferSize += 256;
+
+ if (num == 0 || bufferSize > 65536) // the upper limit is a sanity check to avoid situations where vprintf repeatedly
+ break; // returns -1 because of an error rather than because it needs more space.
+ }
+
+ return String();
+}
+
+//==============================================================================
+int String::getIntValue() const noexcept { return text.getIntValue32(); }
+int64 String::getLargeIntValue() const noexcept { return text.getIntValue64(); }
+float String::getFloatValue() const noexcept { return (float) getDoubleValue(); }
+double String::getDoubleValue() const noexcept { return text.getDoubleValue(); }
+
+int String::getTrailingIntValue() const noexcept
+{
+ int n = 0;
+ int mult = 1;
+ CharPointerType t (text.findTerminatingNull());
+
+ while (--t >= text)
+ {
+ if (! t.isDigit())
+ {
+ if (*t == '-')
+ n = -n;
+
+ break;
+ }
+
+ n += mult * (*t - '0');
+ mult *= 10;
+ }
+
+ return n;
+}
+
+static const char hexDigits[] = "0123456789abcdef";
+
+template <typename Type>
+static String hexToString (Type v)
+{
+ String::CharPointerType::CharType buffer[32];
+ String::CharPointerType::CharType* const end = buffer + numElementsInArray (buffer) - 1;
+ String::CharPointerType::CharType* t = end;
+ *t = 0;
+
+ do
+ {
+ *--t = hexDigits [(int) (v & 15)];
+ v >>= 4;
+
+ } while (v != 0);
+
+ return String (String::CharPointerType (t),
+ String::CharPointerType (end));
+}
+
+String String::toHexString (int number) { return hexToString ((unsigned int) number); }
+String String::toHexString (int64 number) { return hexToString ((uint64) number); }
+String String::toHexString (short number) { return toHexString ((int) (unsigned short) number); }
+
+String String::toHexString (const void* const d, const int size, const int groupSize)
+{
+ if (size <= 0)
+ return String();
+
+ int numChars = (size * 2) + 2;
+ if (groupSize > 0)
+ numChars += size / groupSize;
+
+ String s (PreallocationBytes (sizeof (CharPointerType::CharType) * (size_t) numChars));
+
+ const unsigned char* data = static_cast <const unsigned char*> (d);
+ CharPointerType dest (s.text);
+
+ for (int i = 0; i < size; ++i)
+ {
+ const unsigned char nextByte = *data++;
+ dest.write ((juce_wchar) hexDigits [nextByte >> 4]);
+ dest.write ((juce_wchar) hexDigits [nextByte & 0xf]);
+
+ if (groupSize > 0 && (i % groupSize) == (groupSize - 1) && i < (size - 1))
+ dest.write ((juce_wchar) ' ');
+ }
+
+ dest.writeNull();
+ return s;
+}
+
+int String::getHexValue32() const noexcept { return CharacterFunctions::HexParser<int> ::parse (text); }
+int64 String::getHexValue64() const noexcept { return CharacterFunctions::HexParser<int64>::parse (text); }
+
+//==============================================================================
+String String::createStringFromData (const void* const unknownData, const int size)
+{
+ const uint8* const data = static_cast<const uint8*> (unknownData);
+
+ if (size <= 0 || data == nullptr)
+ return String();
+
+ if (size == 1)
+ return charToString ((juce_wchar) data[0]);
+
+ if (CharPointer_UTF16::isByteOrderMarkBigEndian (data)
+ || CharPointer_UTF16::isByteOrderMarkLittleEndian (data))
+ {
+ const int numChars = size / 2 - 1;
+
+ StringCreationHelper builder ((size_t) numChars);
+
+ const uint16* const src = (const uint16*) (data + 2);
+
+ if (CharPointer_UTF16::isByteOrderMarkBigEndian (data))
+ {
+ for (int i = 0; i < numChars; ++i)
+ builder.write ((juce_wchar) ByteOrder::swapIfLittleEndian (src[i]));
+ }
+ else
+ {
+ for (int i = 0; i < numChars; ++i)
+ builder.write ((juce_wchar) ByteOrder::swapIfBigEndian (src[i]));
+ }
+
+ builder.write (0);
+ return builder.result;
+ }
+
+ const uint8* start = data;
+
+ if (size >= 3 && CharPointer_UTF8::isByteOrderMark (data))
+ start += 3;
+
+ return String (CharPointer_UTF8 ((const char*) start),
+ CharPointer_UTF8 ((const char*) (data + size)));
+}
+
+//==============================================================================
+static const juce_wchar emptyChar = 0;
+
+template <class CharPointerType_Src, class CharPointerType_Dest>
+struct StringEncodingConverter
+{
+ static CharPointerType_Dest convert (const String& s)
+ {
+ String& source = const_cast<String&> (s);
+
+ typedef typename CharPointerType_Dest::CharType DestChar;
+
+ if (source.isEmpty())
+ return CharPointerType_Dest (reinterpret_cast<const DestChar*> (&emptyChar));
+
+ CharPointerType_Src text (source.getCharPointer());
+ const size_t extraBytesNeeded = CharPointerType_Dest::getBytesRequiredFor (text) + sizeof (typename CharPointerType_Dest::CharType);
+ const size_t endOffset = (text.sizeInBytes() + 3) & ~3u; // the new string must be word-aligned or many Windows
+ // functions will fail to read it correctly!
+ source.preallocateBytes (endOffset + extraBytesNeeded);
+ text = source.getCharPointer();
+
+ void* const newSpace = addBytesToPointer (text.getAddress(), (int) endOffset);
+ const CharPointerType_Dest extraSpace (static_cast<DestChar*> (newSpace));
+
+ #if JUCE_DEBUG // (This just avoids spurious warnings from valgrind about the uninitialised bytes at the end of the buffer..)
+ const size_t bytesToClear = (size_t) jmin ((int) extraBytesNeeded, 4);
+ zeromem (addBytesToPointer (newSpace, extraBytesNeeded - bytesToClear), bytesToClear);
+ #endif
+
+ CharPointerType_Dest (extraSpace).writeAll (text);
+ return extraSpace;
+ }
+};
+
+template <>
+struct StringEncodingConverter<CharPointer_UTF8, CharPointer_UTF8>
+{
+ static CharPointer_UTF8 convert (const String& source) noexcept { return CharPointer_UTF8 ((CharPointer_UTF8::CharType*) source.getCharPointer().getAddress()); }
+};
+
+template <>
+struct StringEncodingConverter<CharPointer_UTF16, CharPointer_UTF16>
+{
+ static CharPointer_UTF16 convert (const String& source) noexcept { return CharPointer_UTF16 ((CharPointer_UTF16::CharType*) source.getCharPointer().getAddress()); }
+};
+
+template <>
+struct StringEncodingConverter<CharPointer_UTF32, CharPointer_UTF32>
+{
+ static CharPointer_UTF32 convert (const String& source) noexcept { return CharPointer_UTF32 ((CharPointer_UTF32::CharType*) source.getCharPointer().getAddress()); }
+};
+
+CharPointer_UTF8 String::toUTF8() const { return StringEncodingConverter<CharPointerType, CharPointer_UTF8 >::convert (*this); }
+CharPointer_UTF16 String::toUTF16() const { return StringEncodingConverter<CharPointerType, CharPointer_UTF16>::convert (*this); }
+CharPointer_UTF32 String::toUTF32() const { return StringEncodingConverter<CharPointerType, CharPointer_UTF32>::convert (*this); }
+
+const char* String::toRawUTF8() const
+{
+ return toUTF8().getAddress();
+}
+
+const wchar_t* String::toWideCharPointer() const
+{
+ return StringEncodingConverter<CharPointerType, CharPointer_wchar_t>::convert (*this).getAddress();
+}
+
+std::string String::toStdString() const
+{
+ return std::string (toRawUTF8());
+}
+
+//==============================================================================
+template <class CharPointerType_Src, class CharPointerType_Dest>
+struct StringCopier
+{
+ static size_t copyToBuffer (const CharPointerType_Src source, typename CharPointerType_Dest::CharType* const buffer, const size_t maxBufferSizeBytes)
+ {
+ jassert (((ssize_t) maxBufferSizeBytes) >= 0); // keep this value positive!
+
+ if (buffer == nullptr)
+ return CharPointerType_Dest::getBytesRequiredFor (source) + sizeof (typename CharPointerType_Dest::CharType);
+
+ return CharPointerType_Dest (buffer).writeWithDestByteLimit (source, maxBufferSizeBytes);
+ }
+};
+
+size_t String::copyToUTF8 (CharPointer_UTF8::CharType* const buffer, size_t maxBufferSizeBytes) const noexcept
+{
+ return StringCopier<CharPointerType, CharPointer_UTF8>::copyToBuffer (text, buffer, maxBufferSizeBytes);
+}
+
+size_t String::copyToUTF16 (CharPointer_UTF16::CharType* const buffer, size_t maxBufferSizeBytes) const noexcept
+{
+ return StringCopier<CharPointerType, CharPointer_UTF16>::copyToBuffer (text, buffer, maxBufferSizeBytes);
+}
+
+size_t String::copyToUTF32 (CharPointer_UTF32::CharType* const buffer, size_t maxBufferSizeBytes) const noexcept
+{
+ return StringCopier<CharPointerType, CharPointer_UTF32>::copyToBuffer (text, buffer, maxBufferSizeBytes);
+}
+
+//==============================================================================
+size_t String::getNumBytesAsUTF8() const noexcept
+{
+ return CharPointer_UTF8::getBytesRequiredFor (text);
+}
+
+String String::fromUTF8 (const char* const buffer, int bufferSizeBytes)
+{
+ if (buffer != nullptr)
+ {
+ if (bufferSizeBytes < 0)
+ return String (CharPointer_UTF8 (buffer));
+
+ if (bufferSizeBytes > 0)
+ {
+ jassert (CharPointer_UTF8::isValidString (buffer, bufferSizeBytes));
+ return String (CharPointer_UTF8 (buffer), CharPointer_UTF8 (buffer + bufferSizeBytes));
+ }
+ }
+
+ return String();
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+//==============================================================================
+StringRef::StringRef() noexcept : text ((const String::CharPointerType::CharType*) "\0\0\0")
+{
+}
+
+StringRef::StringRef (const char* stringLiteral) noexcept
+ #if JUCE_STRING_UTF_TYPE != 8
+ : text (nullptr), stringCopy (stringLiteral)
+ #else
+ : text (stringLiteral)
+ #endif
+{
+ #if JUCE_STRING_UTF_TYPE != 8
+ text = stringCopy.getCharPointer();
+ #endif
+
+ jassert (stringLiteral != nullptr); // This must be a valid string literal, not a null pointer!!
+
+ #if JUCE_NATIVE_WCHAR_IS_UTF8
+ /* If you get an assertion here, then you're trying to create a string from 8-bit data
+ that contains values greater than 127. These can NOT be correctly converted to unicode
+ because there's no way for the String class to know what encoding was used to
+ create them. The source data could be UTF-8, ASCII or one of many local code-pages.
+
+ To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
+ string to the StringRef class - so for example if your source data is actually UTF-8,
+ you'd call StringRef (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
+ correctly convert the multi-byte characters to unicode. It's *highly* recommended that
+ you use UTF-8 with escape characters in your source code to represent extended characters,
+ because there's no other way to represent these strings in a way that isn't dependent on
+ the compiler, source code editor and platform.
+ */
+ jassert (CharPointer_ASCII::isValidString (stringLiteral, std::numeric_limits<int>::max()));
+ #endif
+}
+
+StringRef::StringRef (String::CharPointerType stringLiteral) noexcept : text (stringLiteral)
+{
+ jassert (stringLiteral.getAddress() != nullptr); // This must be a valid string literal, not a null pointer!!
+}
+
+StringRef::StringRef (const String& string) noexcept : text (string.getCharPointer()) {}
+
+
+//==============================================================================
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class StringTests : public UnitTest
+{
+public:
+ StringTests() : UnitTest ("String class") {}
+
+ template <class CharPointerType>
+ struct TestUTFConversion
+ {
+ static void test (UnitTest& test, Random& r)
+ {
+ String s (createRandomWideCharString (r));
+
+ typename CharPointerType::CharType buffer [300];
+
+ memset (buffer, 0xff, sizeof (buffer));
+ CharPointerType (buffer).writeAll (s.toUTF32());
+ test.expectEquals (String (CharPointerType (buffer)), s);
+
+ memset (buffer, 0xff, sizeof (buffer));
+ CharPointerType (buffer).writeAll (s.toUTF16());
+ test.expectEquals (String (CharPointerType (buffer)), s);
+
+ memset (buffer, 0xff, sizeof (buffer));
+ CharPointerType (buffer).writeAll (s.toUTF8());
+ test.expectEquals (String (CharPointerType (buffer)), s);
+
+ test.expect (CharPointerType::isValidString (buffer, (int) strlen ((const char*) buffer)));
+ }
+ };
+
+ static String createRandomWideCharString (Random& r)
+ {
+ juce_wchar buffer[50] = { 0 };
+
+ for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
+ {
+ if (r.nextBool())
+ {
+ do
+ {
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
+ }
+ while (! CharPointer_UTF16::canRepresent (buffer[i]));
+ }
+ else
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
+ }
+
+ return CharPointer_UTF32 (buffer);
+ }
+
+ void runTest()
+ {
+ Random r = getRandom();
+
+ {
+ beginTest ("Basics");
+
+ expect (String().length() == 0);
+ expect (String() == String::empty);
+ String s1, s2 ("abcd");
+ expect (s1.isEmpty() && ! s1.isNotEmpty());
+ expect (s2.isNotEmpty() && ! s2.isEmpty());
+ expect (s2.length() == 4);
+ s1 = "abcd";
+ expect (s2 == s1 && s1 == s2);
+ expect (s1 == "abcd" && s1 == L"abcd");
+ expect (String ("abcd") == String (L"abcd"));
+ expect (String ("abcdefg", 4) == L"abcd");
+ expect (String ("abcdefg", 4) == String (L"abcdefg", 4));
+ expect (String::charToString ('x') == "x");
+ expect (String::charToString (0) == String::empty);
+ expect (s2 + "e" == "abcde" && s2 + 'e' == "abcde");
+ expect (s2 + L'e' == "abcde" && s2 + L"e" == "abcde");
+ expect (s1.equalsIgnoreCase ("abcD") && s1 < "abce" && s1 > "abbb");
+ expect (s1.startsWith ("ab") && s1.startsWith ("abcd") && ! s1.startsWith ("abcde"));
+ expect (s1.startsWithIgnoreCase ("aB") && s1.endsWithIgnoreCase ("CD"));
+ expect (s1.endsWith ("bcd") && ! s1.endsWith ("aabcd"));
+ expectEquals (s1.indexOf (String::empty), 0);
+ expectEquals (s1.indexOfIgnoreCase (String::empty), 0);
+ expect (s1.startsWith (String::empty) && s1.endsWith (String::empty) && s1.contains (String::empty));
+ expect (s1.contains ("cd") && s1.contains ("ab") && s1.contains ("abcd"));
+ expect (s1.containsChar ('a'));
+ expect (! s1.containsChar ('x'));
+ expect (! s1.containsChar (0));
+ expect (String ("abc foo bar").containsWholeWord ("abc") && String ("abc foo bar").containsWholeWord ("abc"));
+ }
+
+ {
+ beginTest ("Operations");
+
+ String s ("012345678");
+ expect (s.hashCode() != 0);
+ expect (s.hashCode64() != 0);
+ expect (s.hashCode() != (s + s).hashCode());
+ expect (s.hashCode64() != (s + s).hashCode64());
+ expect (s.compare (String ("012345678")) == 0);
+ expect (s.compare (String ("012345679")) < 0);
+ expect (s.compare (String ("012345676")) > 0);
+ expect (String("a").compareNatural ("A") == 0);
+ expect (String("A").compareNatural ("B") < 0);
+ expect (String("a").compareNatural ("B") < 0);
+ expect (String("10").compareNatural ("2") > 0);
+ expect (String("Abc 10").compareNatural ("aBC 2") > 0);
+ expect (String("Abc 1").compareNatural ("aBC 2") < 0);
+ expect (s.substring (2, 3) == String::charToString (s[2]));
+ expect (s.substring (0, 1) == String::charToString (s[0]));
+ expect (s.getLastCharacter() == s [s.length() - 1]);
+ expect (String::charToString (s.getLastCharacter()) == s.getLastCharacters (1));
+ expect (s.substring (0, 3) == L"012");
+ expect (s.substring (0, 100) == s);
+ expect (s.substring (-1, 100) == s);
+ expect (s.substring (3) == "345678");
+ expect (s.indexOf (String (L"45")) == 4);
+ expect (String ("444445").indexOf ("45") == 4);
+ expect (String ("444445").lastIndexOfChar ('4') == 4);
+ expect (String ("45454545x").lastIndexOf (String (L"45")) == 6);
+ expect (String ("45454545x").lastIndexOfAnyOf ("456") == 7);
+ expect (String ("45454545x").lastIndexOfAnyOf (String (L"456x")) == 8);
+ expect (String ("abABaBaBa").lastIndexOfIgnoreCase ("aB") == 6);
+ expect (s.indexOfChar (L'4') == 4);
+ expect (s + s == "012345678012345678");
+ expect (s.startsWith (s));
+ expect (s.startsWith (s.substring (0, 4)));
+ expect (s.startsWith (s.dropLastCharacters (4)));
+ expect (s.endsWith (s.substring (5)));
+ expect (s.endsWith (s));
+ expect (s.contains (s.substring (3, 6)));
+ expect (s.contains (s.substring (3)));
+ expect (s.startsWithChar (s[0]));
+ expect (s.endsWithChar (s.getLastCharacter()));
+ expect (s [s.length()] == 0);
+ expect (String ("abcdEFGH").toLowerCase() == String ("abcdefgh"));
+ expect (String ("abcdEFGH").toUpperCase() == String ("ABCDEFGH"));
+
+ String s2 ("123");
+ s2 << ((int) 4) << ((short) 5) << "678" << L"9" << '0';
+ s2 += "xyz";
+ expect (s2 == "1234567890xyz");
+ s2 += (int) 123;
+ expect (s2 == "1234567890xyz123");
+ s2 += (int64) 123;
+ expect (s2 == "1234567890xyz123123");
+
+ beginTest ("Numeric conversions");
+ expect (String::empty.getIntValue() == 0);
+ expect (String::empty.getDoubleValue() == 0.0);
+ expect (String::empty.getFloatValue() == 0.0f);
+ expect (s.getIntValue() == 12345678);
+ expect (s.getLargeIntValue() == (int64) 12345678);
+ expect (s.getDoubleValue() == 12345678.0);
+ expect (s.getFloatValue() == 12345678.0f);
+ expect (String (-1234).getIntValue() == -1234);
+ expect (String ((int64) -1234).getLargeIntValue() == -1234);
+ expect (String (-1234.56).getDoubleValue() == -1234.56);
+ expect (String (-1234.56f).getFloatValue() == -1234.56f);
+ expect (String (std::numeric_limits<int>::max()).getIntValue() == std::numeric_limits<int>::max());
+ expect (String (std::numeric_limits<int>::min()).getIntValue() == std::numeric_limits<int>::min());
+ expect (String (std::numeric_limits<int64>::max()).getLargeIntValue() == std::numeric_limits<int64>::max());
+ expect (String (std::numeric_limits<int64>::min()).getLargeIntValue() == std::numeric_limits<int64>::min());
+ expect (("xyz" + s).getTrailingIntValue() == s.getIntValue());
+ expect (s.getHexValue32() == 0x12345678);
+ expect (s.getHexValue64() == (int64) 0x12345678);
+ expect (String::toHexString (0x1234abcd).equalsIgnoreCase ("1234abcd"));
+ expect (String::toHexString ((int64) 0x1234abcd).equalsIgnoreCase ("1234abcd"));
+ expect (String::toHexString ((short) 0x12ab).equalsIgnoreCase ("12ab"));
+
+ unsigned char data[] = { 1, 2, 3, 4, 0xa, 0xb, 0xc, 0xd };
+ expect (String::toHexString (data, 8, 0).equalsIgnoreCase ("010203040a0b0c0d"));
+ expect (String::toHexString (data, 8, 1).equalsIgnoreCase ("01 02 03 04 0a 0b 0c 0d"));
+ expect (String::toHexString (data, 8, 2).equalsIgnoreCase ("0102 0304 0a0b 0c0d"));
+
+ beginTest ("Subsections");
+ String s3;
+ s3 = "abcdeFGHIJ";
+ expect (s3.equalsIgnoreCase ("ABCdeFGhiJ"));
+ expect (s3.compareIgnoreCase (L"ABCdeFGhiJ") == 0);
+ expect (s3.containsIgnoreCase (s3.substring (3)));
+ expect (s3.indexOfAnyOf ("xyzf", 2, true) == 5);
+ expect (s3.indexOfAnyOf (String (L"xyzf"), 2, false) == -1);
+ expect (s3.indexOfAnyOf ("xyzF", 2, false) == 5);
+ expect (s3.containsAnyOf (String (L"zzzFs")));
+ expect (s3.startsWith ("abcd"));
+ expect (s3.startsWithIgnoreCase (String (L"abCD")));
+ expect (s3.startsWith (String::empty));
+ expect (s3.startsWithChar ('a'));
+ expect (s3.endsWith (String ("HIJ")));
+ expect (s3.endsWithIgnoreCase (String (L"Hij")));
+ expect (s3.endsWith (String::empty));
+ expect (s3.endsWithChar (L'J'));
+ expect (s3.indexOf ("HIJ") == 7);
+ expect (s3.indexOf (String (L"HIJK")) == -1);
+ expect (s3.indexOfIgnoreCase ("hij") == 7);
+ expect (s3.indexOfIgnoreCase (String (L"hijk")) == -1);
+ expect (s3.toStdString() == s3.toRawUTF8());
+
+ String s4 (s3);
+ s4.append (String ("xyz123"), 3);
+ expect (s4 == s3 + "xyz");
+
+ expect (String (1234) < String (1235));
+ expect (String (1235) > String (1234));
+ expect (String (1234) >= String (1234));
+ expect (String (1234) <= String (1234));
+ expect (String (1235) >= String (1234));
+ expect (String (1234) <= String (1235));
+
+ String s5 ("word word2 word3");
+ expect (s5.containsWholeWord (String ("word2")));
+ expect (s5.indexOfWholeWord ("word2") == 5);
+ expect (s5.containsWholeWord (String (L"word")));
+ expect (s5.containsWholeWord ("word3"));
+ expect (s5.containsWholeWord (s5));
+ expect (s5.containsWholeWordIgnoreCase (String (L"Word2")));
+ expect (s5.indexOfWholeWordIgnoreCase ("Word2") == 5);
+ expect (s5.containsWholeWordIgnoreCase (String (L"Word")));
+ expect (s5.containsWholeWordIgnoreCase ("Word3"));
+ expect (! s5.containsWholeWordIgnoreCase (String (L"Wordx")));
+ expect (! s5.containsWholeWordIgnoreCase ("xWord2"));
+ expect (s5.containsNonWhitespaceChars());
+ expect (s5.containsOnly ("ordw23 "));
+ expect (! String (" \n\r\t").containsNonWhitespaceChars());
+
+ expect (s5.matchesWildcard (String (L"wor*"), false));
+ expect (s5.matchesWildcard ("wOr*", true));
+ expect (s5.matchesWildcard (String (L"*word3"), true));
+ expect (s5.matchesWildcard ("*word?", true));
+ expect (s5.matchesWildcard (String (L"Word*3"), true));
+ expect (! s5.matchesWildcard (String (L"*34"), true));
+ expect (String ("xx**y").matchesWildcard ("*y", true));
+ expect (String ("xx**y").matchesWildcard ("x*y", true));
+ expect (String ("xx**y").matchesWildcard ("xx*y", true));
+ expect (String ("xx**y").matchesWildcard ("xx*", true));
+ expect (String ("xx?y").matchesWildcard ("x??y", true));
+ expect (String ("xx?y").matchesWildcard ("xx?y", true));
+ expect (! String ("xx?y").matchesWildcard ("xx?y?", true));
+ expect (String ("xx?y").matchesWildcard ("xx??", true));
+
+ expectEquals (s5.fromFirstOccurrenceOf (String::empty, true, false), s5);
+ expectEquals (s5.fromFirstOccurrenceOf ("xword2", true, false), s5.substring (100));
+ expectEquals (s5.fromFirstOccurrenceOf (String (L"word2"), true, false), s5.substring (5));
+ expectEquals (s5.fromFirstOccurrenceOf ("Word2", true, true), s5.substring (5));
+ expectEquals (s5.fromFirstOccurrenceOf ("word2", false, false), s5.getLastCharacters (6));
+ expectEquals (s5.fromFirstOccurrenceOf ("Word2", false, true), s5.getLastCharacters (6));
+
+ expectEquals (s5.fromLastOccurrenceOf (String::empty, true, false), s5);
+ expectEquals (s5.fromLastOccurrenceOf ("wordx", true, false), s5);
+ expectEquals (s5.fromLastOccurrenceOf ("word", true, false), s5.getLastCharacters (5));
+ expectEquals (s5.fromLastOccurrenceOf ("worD", true, true), s5.getLastCharacters (5));
+ expectEquals (s5.fromLastOccurrenceOf ("word", false, false), s5.getLastCharacters (1));
+ expectEquals (s5.fromLastOccurrenceOf ("worD", false, true), s5.getLastCharacters (1));
+
+ expect (s5.upToFirstOccurrenceOf (String::empty, true, false).isEmpty());
+ expectEquals (s5.upToFirstOccurrenceOf ("word4", true, false), s5);
+ expectEquals (s5.upToFirstOccurrenceOf ("word2", true, false), s5.substring (0, 10));
+ expectEquals (s5.upToFirstOccurrenceOf ("Word2", true, true), s5.substring (0, 10));
+ expectEquals (s5.upToFirstOccurrenceOf ("word2", false, false), s5.substring (0, 5));
+ expectEquals (s5.upToFirstOccurrenceOf ("Word2", false, true), s5.substring (0, 5));
+
+ expectEquals (s5.upToLastOccurrenceOf (String::empty, true, false), s5);
+ expectEquals (s5.upToLastOccurrenceOf ("zword", true, false), s5);
+ expectEquals (s5.upToLastOccurrenceOf ("word", true, false), s5.dropLastCharacters (1));
+ expectEquals (s5.dropLastCharacters(1).upToLastOccurrenceOf ("word", true, false), s5.dropLastCharacters (1));
+ expectEquals (s5.upToLastOccurrenceOf ("Word", true, true), s5.dropLastCharacters (1));
+ expectEquals (s5.upToLastOccurrenceOf ("word", false, false), s5.dropLastCharacters (5));
+ expectEquals (s5.upToLastOccurrenceOf ("Word", false, true), s5.dropLastCharacters (5));
+
+ expectEquals (s5.replace ("word", "xyz", false), String ("xyz xyz2 xyz3"));
+ expect (s5.replace ("Word", "xyz", true) == "xyz xyz2 xyz3");
+ expect (s5.dropLastCharacters (1).replace ("Word", String ("xyz"), true) == L"xyz xyz2 xyz");
+ expect (s5.replace ("Word", "", true) == " 2 3");
+ expectEquals (s5.replace ("Word2", "xyz", true), String ("word xyz word3"));
+ expect (s5.replaceCharacter (L'w', 'x') != s5);
+ expectEquals (s5.replaceCharacter ('w', L'x').replaceCharacter ('x', 'w'), s5);
+ expect (s5.replaceCharacters ("wo", "xy") != s5);
+ expectEquals (s5.replaceCharacters ("wo", "xy").replaceCharacters ("xy", "wo"), s5);
+ expectEquals (s5.retainCharacters ("1wordxya"), String ("wordwordword"));
+ expect (s5.retainCharacters (String::empty).isEmpty());
+ expect (s5.removeCharacters ("1wordxya") == " 2 3");
+ expectEquals (s5.removeCharacters (String::empty), s5);
+ expect (s5.initialSectionContainingOnly ("word") == L"word");
+ expect (String ("word").initialSectionContainingOnly ("word") == L"word");
+ expectEquals (s5.initialSectionNotContaining (String ("xyz ")), String ("word"));
+ expectEquals (s5.initialSectionNotContaining (String (";[:'/")), s5);
+ expect (! s5.isQuotedString());
+ expect (s5.quoted().isQuotedString());
+ expect (! s5.quoted().unquoted().isQuotedString());
+ expect (! String ("x'").isQuotedString());
+ expect (String ("'x").isQuotedString());
+
+ String s6 (" \t xyz \t\r\n");
+ expectEquals (s6.trim(), String ("xyz"));
+ expect (s6.trim().trim() == "xyz");
+ expectEquals (s5.trim(), s5);
+ expectEquals (s6.trimStart().trimEnd(), s6.trim());
+ expectEquals (s6.trimStart().trimEnd(), s6.trimEnd().trimStart());
+ expectEquals (s6.trimStart().trimStart().trimEnd().trimEnd(), s6.trimEnd().trimStart());
+ expect (s6.trimStart() != s6.trimEnd());
+ expectEquals (("\t\r\n " + s6 + "\t\n \r").trim(), s6.trim());
+ expect (String::repeatedString ("xyz", 3) == L"xyzxyzxyz");
+ }
+
+ {
+ beginTest ("UTF conversions");
+
+ TestUTFConversion <CharPointer_UTF32>::test (*this, r);
+ TestUTFConversion <CharPointer_UTF8>::test (*this, r);
+ TestUTFConversion <CharPointer_UTF16>::test (*this, r);
+ }
+
+ {
+ beginTest ("StringArray");
+
+ StringArray s;
+ s.addTokens ("4,3,2,1,0", ";,", "x");
+ expectEquals (s.size(), 5);
+
+ expectEquals (s.joinIntoString ("-"), String ("4-3-2-1-0"));
+ s.remove (2);
+ expectEquals (s.joinIntoString ("--"), String ("4--3--1--0"));
+ expectEquals (s.joinIntoString (String::empty), String ("4310"));
+ s.clear();
+ expectEquals (s.joinIntoString ("x"), String::empty);
+
+ StringArray toks;
+ toks.addTokens ("x,,", ";,", "");
+ expectEquals (toks.size(), 3);
+ expectEquals (toks.joinIntoString ("-"), String ("x--"));
+ toks.clear();
+
+ toks.addTokens (",x,", ";,", "");
+ expectEquals (toks.size(), 3);
+ expectEquals (toks.joinIntoString ("-"), String ("-x-"));
+ toks.clear();
+
+ toks.addTokens ("x,'y,z',", ";,", "'");
+ expectEquals (toks.size(), 3);
+ expectEquals (toks.joinIntoString ("-"), String ("x-'y,z'-"));
+ }
+
+ {
+ beginTest ("var");
+
+ var v1 = 0;
+ var v2 = 0.1;
+ var v3 = "0.1";
+ var v4 = (int64) 0;
+ var v5 = 0.0;
+ expect (! v2.equals (v1));
+ expect (! v1.equals (v2));
+ expect (v2.equals (v3));
+ expect (v3.equals (v2));
+ expect (! v3.equals (v1));
+ expect (! v1.equals (v3));
+ expect (v1.equals (v4));
+ expect (v4.equals (v1));
+ expect (v5.equals (v4));
+ expect (v4.equals (v5));
+ expect (! v2.equals (v4));
+ expect (! v4.equals (v2));
+ }
+ }
+};
+
+static StringTests stringUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.h
new file mode 100644
index 0000000..4873bd9
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_String.h
@@ -0,0 +1,1370 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STRING_H_INCLUDED
+#define JUCE_STRING_H_INCLUDED
+
+
+//==============================================================================
+/**
+ The JUCE String class!
+
+ Using a reference-counted internal representation, these strings are fast
+ and efficient, and there are methods to do just about any operation you'll ever
+ dream of.
+
+ @see StringArray, StringPairArray
+*/
+class JUCE_API String
+{
+public:
+ //==============================================================================
+ /** Creates an empty string.
+ @see empty
+ */
+ String() noexcept;
+
+ /** Creates a copy of another string. */
+ String (const String& other) noexcept;
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ String (String&& other) noexcept;
+ #endif
+
+ /** Creates a string from a zero-terminated ascii text string.
+
+ The string passed-in must not contain any characters with a value above 127, because
+ these can't be converted to unicode without knowing the original encoding that was
+ used to create the string. If you attempt to pass-in values above 127, you'll get an
+ assertion.
+
+ To create strings with extended characters from UTF-8, you should explicitly call
+ String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you
+ use UTF-8 with escape characters in your source code to represent extended characters,
+ because there's no other way to represent unicode strings in a way that isn't dependent
+ on the compiler, source code editor and platform.
+ */
+ String (const char* text);
+
+ /** Creates a string from a string of 8-bit ascii characters.
+
+ The string passed-in must not contain any characters with a value above 127, because
+ these can't be converted to unicode without knowing the original encoding that was
+ used to create the string. If you attempt to pass-in values above 127, you'll get an
+ assertion.
+
+ To create strings with extended characters from UTF-8, you should explicitly call
+ String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you
+ use UTF-8 with escape characters in your source code to represent extended characters,
+ because there's no other way to represent unicode strings in a way that isn't dependent
+ on the compiler, source code editor and platform.
+
+ This will use up to the first maxChars characters of the string (or less if the string
+ is actually shorter).
+ */
+ String (const char* text, size_t maxChars);
+
+ /** Creates a string from a whcar_t character string.
+ Depending on the platform, this may be treated as either UTF-32 or UTF-16.
+ */
+ String (const wchar_t* text);
+
+ /** Creates a string from a whcar_t character string.
+ Depending on the platform, this may be treated as either UTF-32 or UTF-16.
+ */
+ String (const wchar_t* text, size_t maxChars);
+
+ //==============================================================================
+ /** Creates a string from a UTF-8 character string */
+ String (const CharPointer_UTF8 text);
+
+ /** Creates a string from a UTF-8 character string */
+ String (const CharPointer_UTF8 text, size_t maxChars);
+
+ /** Creates a string from a UTF-8 character string */
+ String (const CharPointer_UTF8 start, const CharPointer_UTF8 end);
+
+ //==============================================================================
+ /** Creates a string from a UTF-16 character string */
+ String (const CharPointer_UTF16 text);
+
+ /** Creates a string from a UTF-16 character string */
+ String (const CharPointer_UTF16 text, size_t maxChars);
+
+ /** Creates a string from a UTF-16 character string */
+ String (const CharPointer_UTF16 start, const CharPointer_UTF16 end);
+
+ //==============================================================================
+ /** Creates a string from a UTF-32 character string */
+ String (const CharPointer_UTF32 text);
+
+ /** Creates a string from a UTF-32 character string */
+ String (const CharPointer_UTF32 text, size_t maxChars);
+
+ /** Creates a string from a UTF-32 character string */
+ String (const CharPointer_UTF32 start, const CharPointer_UTF32 end);
+
+ //==============================================================================
+ /** Creates a string from an ASCII character string */
+ String (const CharPointer_ASCII text);
+
+ /** Creates a string from a UTF-8 encoded std::string. */
+ String (const std::string&);
+
+ //==============================================================================
+ /** Creates a string from a single character. */
+ static String charToString (juce_wchar character);
+
+ /** Destructor. */
+ ~String() noexcept;
+
+ //==============================================================================
+ /** This is an empty string that can be used whenever one is needed.
+
+ It's better to use this than String() because it explains what's going on
+ and is more efficient.
+ */
+ static const String empty;
+
+ /** This is the character encoding type used internally to store the string.
+
+ By setting the value of JUCE_STRING_UTF_TYPE to 8, 16, or 32, you can change the
+ internal storage format of the String class. UTF-8 uses the least space (if your strings
+ contain few extended characters), but call operator[] involves iterating the string to find
+ the required index. UTF-32 provides instant random access to its characters, but uses 4 bytes
+ per character to store them. UTF-16 uses more space than UTF-8 and is also slow to index,
+ but is the native wchar_t format used in Windows.
+
+ It doesn't matter too much which format you pick, because the toUTF8(), toUTF16() and
+ toUTF32() methods let you access the string's content in any of the other formats.
+ */
+ #if (JUCE_STRING_UTF_TYPE == 32)
+ typedef CharPointer_UTF32 CharPointerType;
+ #elif (JUCE_STRING_UTF_TYPE == 16)
+ typedef CharPointer_UTF16 CharPointerType;
+ #elif (DOXYGEN || JUCE_STRING_UTF_TYPE == 8)
+ typedef CharPointer_UTF8 CharPointerType;
+ #else
+ #error "You must set the value of JUCE_STRING_UTF_TYPE to be either 8, 16, or 32!"
+ #endif
+
+ //==============================================================================
+ /** Generates a probably-unique 32-bit hashcode from this string. */
+ int hashCode() const noexcept;
+
+ /** Generates a probably-unique 64-bit hashcode from this string. */
+ int64 hashCode64() const noexcept;
+
+ /** Generates a probably-unique hashcode from this string. */
+ std::size_t hash() const noexcept;
+
+ /** Returns the number of characters in the string. */
+ int length() const noexcept;
+
+ //==============================================================================
+ // Assignment and concatenation operators..
+
+ /** Replaces this string's contents with another string. */
+ String& operator= (const String& other) noexcept;
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ String& operator= (String&& other) noexcept;
+ #endif
+
+ /** Appends another string at the end of this one. */
+ String& operator+= (const String& stringToAppend);
+ /** Appends another string at the end of this one. */
+ String& operator+= (const char* textToAppend);
+ /** Appends another string at the end of this one. */
+ String& operator+= (const wchar_t* textToAppend);
+ /** Appends a decimal number at the end of this string. */
+ String& operator+= (int numberToAppend);
+ /** Appends a decimal number at the end of this string. */
+ String& operator+= (int64 numberToAppend);
+ /** Appends a character at the end of this string. */
+ String& operator+= (char characterToAppend);
+ /** Appends a character at the end of this string. */
+ String& operator+= (wchar_t characterToAppend);
+ #if ! JUCE_NATIVE_WCHAR_IS_UTF32
+ /** Appends a character at the end of this string. */
+ String& operator+= (juce_wchar characterToAppend);
+ #endif
+
+ /** Appends a string to the end of this one.
+
+ @param textToAppend the string to add
+ @param maxCharsToTake the maximum number of characters to take from the string passed in
+ */
+ void append (const String& textToAppend, size_t maxCharsToTake);
+
+ /** Appends a string to the end of this one.
+
+ @param startOfTextToAppend the start of the string to add. This must not be a nullptr
+ @param endOfTextToAppend the end of the string to add. This must not be a nullptr
+ */
+ void appendCharPointer (const CharPointerType startOfTextToAppend,
+ const CharPointerType endOfTextToAppend);
+
+ /** Appends a string to the end of this one.
+
+ @param startOfTextToAppend the start of the string to add. This must not be a nullptr
+ @param endOfTextToAppend the end of the string to add. This must not be a nullptr
+ */
+ template <class CharPointer>
+ void appendCharPointer (const CharPointer startOfTextToAppend,
+ const CharPointer endOfTextToAppend)
+ {
+ jassert (startOfTextToAppend.getAddress() != nullptr && endOfTextToAppend.getAddress() != nullptr);
+
+ size_t extraBytesNeeded = 0, numChars = 1;
+
+ for (CharPointer t (startOfTextToAppend); t != endOfTextToAppend && ! t.isEmpty(); ++numChars)
+ extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance());
+
+ if (extraBytesNeeded > 0)
+ {
+ const size_t byteOffsetOfNull = getByteOffsetOfEnd();
+
+ preallocateBytes (byteOffsetOfNull + extraBytesNeeded);
+ CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull))
+ .writeWithCharLimit (startOfTextToAppend, (int) numChars);
+ }
+ }
+
+ /** Appends a string to the end of this one. */
+ void appendCharPointer (const CharPointerType textToAppend);
+
+ /** Appends a string to the end of this one.
+
+ @param textToAppend the string to add
+ @param maxCharsToTake the maximum number of characters to take from the string passed in
+ */
+ template <class CharPointer>
+ void appendCharPointer (const CharPointer textToAppend, size_t maxCharsToTake)
+ {
+ if (textToAppend.getAddress() != nullptr)
+ {
+ size_t extraBytesNeeded = 0, numChars = 1;
+
+ for (CharPointer t (textToAppend); numChars <= maxCharsToTake && ! t.isEmpty(); ++numChars)
+ extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance());
+
+ if (extraBytesNeeded > 0)
+ {
+ const size_t byteOffsetOfNull = getByteOffsetOfEnd();
+
+ preallocateBytes (byteOffsetOfNull + extraBytesNeeded);
+ CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull))
+ .writeWithCharLimit (textToAppend, (int) numChars);
+ }
+ }
+ }
+
+ /** Appends a string to the end of this one. */
+ template <class CharPointer>
+ void appendCharPointer (const CharPointer textToAppend)
+ {
+ appendCharPointer (textToAppend, std::numeric_limits<size_t>::max());
+ }
+
+ //==============================================================================
+ // Comparison methods..
+
+ /** Returns true if the string contains no characters.
+ Note that there's also an isNotEmpty() method to help write readable code.
+ @see containsNonWhitespaceChars()
+ */
+ inline bool isEmpty() const noexcept { return text[0] == 0; }
+
+ /** Returns true if the string contains at least one character.
+ Note that there's also an isEmpty() method to help write readable code.
+ @see containsNonWhitespaceChars()
+ */
+ inline bool isNotEmpty() const noexcept { return text[0] != 0; }
+
+ /** Resets this string to be empty. */
+ void clear() noexcept;
+
+ /** Case-insensitive comparison with another string. */
+ bool equalsIgnoreCase (const String& other) const noexcept;
+
+ /** Case-insensitive comparison with another string. */
+ bool equalsIgnoreCase (StringRef other) const noexcept;
+
+ /** Case-insensitive comparison with another string. */
+ bool equalsIgnoreCase (const wchar_t* other) const noexcept;
+
+ /** Case-insensitive comparison with another string. */
+ bool equalsIgnoreCase (const char* other) const noexcept;
+
+ /** Case-sensitive comparison with another string.
+ @returns 0 if the two strings are identical; negative if this string comes before
+ the other one alphabetically, or positive if it comes after it.
+ */
+ int compare (const String& other) const noexcept;
+
+ /** Case-sensitive comparison with another string.
+ @returns 0 if the two strings are identical; negative if this string comes before
+ the other one alphabetically, or positive if it comes after it.
+ */
+ int compare (const char* other) const noexcept;
+
+ /** Case-sensitive comparison with another string.
+ @returns 0 if the two strings are identical; negative if this string comes before
+ the other one alphabetically, or positive if it comes after it.
+ */
+ int compare (const wchar_t* other) const noexcept;
+
+ /** Case-insensitive comparison with another string.
+ @returns 0 if the two strings are identical; negative if this string comes before
+ the other one alphabetically, or positive if it comes after it.
+ */
+ int compareIgnoreCase (const String& other) const noexcept;
+
+ /** Compares two strings, taking into account textual characteristics like numbers and spaces.
+
+ This comparison is case-insensitive and can detect words and embedded numbers in the
+ strings, making it good for sorting human-readable lists of things like filenames.
+
+ @returns 0 if the two strings are identical; negative if this string comes before
+ the other one alphabetically, or positive if it comes after it.
+ */
+ int compareNatural (StringRef other) const noexcept;
+
+ /** Tests whether the string begins with another string.
+ If the parameter is an empty string, this will always return true.
+ Uses a case-sensitive comparison.
+ */
+ bool startsWith (StringRef text) const noexcept;
+
+ /** Tests whether the string begins with a particular character.
+ If the character is 0, this will always return false.
+ Uses a case-sensitive comparison.
+ */
+ bool startsWithChar (juce_wchar character) const noexcept;
+
+ /** Tests whether the string begins with another string.
+ If the parameter is an empty string, this will always return true.
+ Uses a case-insensitive comparison.
+ */
+ bool startsWithIgnoreCase (StringRef text) const noexcept;
+
+ /** Tests whether the string ends with another string.
+ If the parameter is an empty string, this will always return true.
+ Uses a case-sensitive comparison.
+ */
+ bool endsWith (StringRef text) const noexcept;
+
+ /** Tests whether the string ends with a particular character.
+ If the character is 0, this will always return false.
+ Uses a case-sensitive comparison.
+ */
+ bool endsWithChar (juce_wchar character) const noexcept;
+
+ /** Tests whether the string ends with another string.
+ If the parameter is an empty string, this will always return true.
+ Uses a case-insensitive comparison.
+ */
+ bool endsWithIgnoreCase (StringRef text) const noexcept;
+
+ /** Tests whether the string contains another substring.
+ If the parameter is an empty string, this will always return true.
+ Uses a case-sensitive comparison.
+ */
+ bool contains (StringRef text) const noexcept;
+
+ /** Tests whether the string contains a particular character.
+ Uses a case-sensitive comparison.
+ */
+ bool containsChar (juce_wchar character) const noexcept;
+
+ /** Tests whether the string contains another substring.
+ Uses a case-insensitive comparison.
+ */
+ bool containsIgnoreCase (StringRef text) const noexcept;
+
+ /** Tests whether the string contains another substring as a distinct word.
+
+ @returns true if the string contains this word, surrounded by
+ non-alphanumeric characters
+ @see indexOfWholeWord, containsWholeWordIgnoreCase
+ */
+ bool containsWholeWord (StringRef wordToLookFor) const noexcept;
+
+ /** Tests whether the string contains another substring as a distinct word.
+
+ @returns true if the string contains this word, surrounded by
+ non-alphanumeric characters
+ @see indexOfWholeWordIgnoreCase, containsWholeWord
+ */
+ bool containsWholeWordIgnoreCase (StringRef wordToLookFor) const noexcept;
+
+ /** Finds an instance of another substring if it exists as a distinct word.
+
+ @returns if the string contains this word, surrounded by non-alphanumeric characters,
+ then this will return the index of the start of the substring. If it isn't
+ found, then it will return -1
+ @see indexOfWholeWordIgnoreCase, containsWholeWord
+ */
+ int indexOfWholeWord (StringRef wordToLookFor) const noexcept;
+
+ /** Finds an instance of another substring if it exists as a distinct word.
+
+ @returns if the string contains this word, surrounded by non-alphanumeric characters,
+ then this will return the index of the start of the substring. If it isn't
+ found, then it will return -1
+ @see indexOfWholeWord, containsWholeWordIgnoreCase
+ */
+ int indexOfWholeWordIgnoreCase (StringRef wordToLookFor) const noexcept;
+
+ /** Looks for any of a set of characters in the string.
+ Uses a case-sensitive comparison.
+
+ @returns true if the string contains any of the characters from
+ the string that is passed in.
+ */
+ bool containsAnyOf (StringRef charactersItMightContain) const noexcept;
+
+ /** Looks for a set of characters in the string.
+ Uses a case-sensitive comparison.
+
+ @returns Returns false if any of the characters in this string do not occur in
+ the parameter string. If this string is empty, the return value will
+ always be true.
+ */
+ bool containsOnly (StringRef charactersItMightContain) const noexcept;
+
+ /** Returns true if this string contains any non-whitespace characters.
+
+ This will return false if the string contains only whitespace characters, or
+ if it's empty.
+
+ It is equivalent to calling "myString.trim().isNotEmpty()".
+ */
+ bool containsNonWhitespaceChars() const noexcept;
+
+ /** Returns true if the string matches this simple wildcard expression.
+
+ So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true.
+
+ This isn't a full-blown regex though! The only wildcard characters supported
+ are "*" and "?". It's mainly intended for filename pattern matching.
+ */
+ bool matchesWildcard (StringRef wildcard, bool ignoreCase) const noexcept;
+
+ //==============================================================================
+ // Substring location methods..
+
+ /** Searches for a character inside this string.
+ Uses a case-sensitive comparison.
+ @returns the index of the first occurrence of the character in this
+ string, or -1 if it's not found.
+ */
+ int indexOfChar (juce_wchar characterToLookFor) const noexcept;
+
+ /** Searches for a character inside this string.
+ Uses a case-sensitive comparison.
+ @param startIndex the index from which the search should proceed
+ @param characterToLookFor the character to look for
+ @returns the index of the first occurrence of the character in this
+ string, or -1 if it's not found.
+ */
+ int indexOfChar (int startIndex, juce_wchar characterToLookFor) const noexcept;
+
+ /** Returns the index of the first character that matches one of the characters
+ passed-in to this method.
+
+ This scans the string, beginning from the startIndex supplied, and if it finds
+ a character that appears in the string charactersToLookFor, it returns its index.
+
+ If none of these characters are found, it returns -1.
+
+ If ignoreCase is true, the comparison will be case-insensitive.
+
+ @see indexOfChar, lastIndexOfAnyOf
+ */
+ int indexOfAnyOf (StringRef charactersToLookFor,
+ int startIndex = 0,
+ bool ignoreCase = false) const noexcept;
+
+ /** Searches for a substring within this string.
+ Uses a case-sensitive comparison.
+ @returns the index of the first occurrence of this substring, or -1 if it's not found.
+ If textToLookFor is an empty string, this will always return 0.
+ */
+ int indexOf (StringRef textToLookFor) const noexcept;
+
+ /** Searches for a substring within this string.
+ Uses a case-sensitive comparison.
+ @param startIndex the index from which the search should proceed
+ @param textToLookFor the string to search for
+ @returns the index of the first occurrence of this substring, or -1 if it's not found.
+ If textToLookFor is an empty string, this will always return -1.
+ */
+ int indexOf (int startIndex, StringRef textToLookFor) const noexcept;
+
+ /** Searches for a substring within this string.
+ Uses a case-insensitive comparison.
+ @returns the index of the first occurrence of this substring, or -1 if it's not found.
+ If textToLookFor is an empty string, this will always return 0.
+ */
+ int indexOfIgnoreCase (StringRef textToLookFor) const noexcept;
+
+ /** Searches for a substring within this string.
+ Uses a case-insensitive comparison.
+ @param startIndex the index from which the search should proceed
+ @param textToLookFor the string to search for
+ @returns the index of the first occurrence of this substring, or -1 if it's not found.
+ If textToLookFor is an empty string, this will always return -1.
+ */
+ int indexOfIgnoreCase (int startIndex, StringRef textToLookFor) const noexcept;
+
+ /** Searches for a character inside this string (working backwards from the end of the string).
+ Uses a case-sensitive comparison.
+ @returns the index of the last occurrence of the character in this string, or -1 if it's not found.
+ */
+ int lastIndexOfChar (juce_wchar character) const noexcept;
+
+ /** Searches for a substring inside this string (working backwards from the end of the string).
+ Uses a case-sensitive comparison.
+ @returns the index of the start of the last occurrence of the substring within this string,
+ or -1 if it's not found. If textToLookFor is an empty string, this will always return -1.
+ */
+ int lastIndexOf (StringRef textToLookFor) const noexcept;
+
+ /** Searches for a substring inside this string (working backwards from the end of the string).
+ Uses a case-insensitive comparison.
+ @returns the index of the start of the last occurrence of the substring within this string, or -1
+ if it's not found. If textToLookFor is an empty string, this will always return -1.
+ */
+ int lastIndexOfIgnoreCase (StringRef textToLookFor) const noexcept;
+
+ /** Returns the index of the last character in this string that matches one of the
+ characters passed-in to this method.
+
+ This scans the string backwards, starting from its end, and if it finds
+ a character that appears in the string charactersToLookFor, it returns its index.
+
+ If none of these characters are found, it returns -1.
+
+ If ignoreCase is true, the comparison will be case-insensitive.
+
+ @see lastIndexOf, indexOfAnyOf
+ */
+ int lastIndexOfAnyOf (StringRef charactersToLookFor,
+ bool ignoreCase = false) const noexcept;
+
+
+ //==============================================================================
+ // Substring extraction and manipulation methods..
+
+ /** Returns the character at this index in the string.
+ In a release build, no checks are made to see if the index is within a valid range, so be
+ careful! In a debug build, the index is checked and an assertion fires if it's out-of-range.
+
+ Also beware that depending on the encoding format that the string is using internally, this
+ method may execute in either O(1) or O(n) time, so be careful when using it in your algorithms.
+ If you're scanning through a string to inspect its characters, you should never use this operator
+ for random access, it's far more efficient to call getCharPointer() to return a pointer, and
+ then to use that to iterate the string.
+ @see getCharPointer
+ */
+ juce_wchar operator[] (int index) const noexcept;
+
+ /** Returns the final character of the string.
+ If the string is empty this will return 0.
+ */
+ juce_wchar getLastCharacter() const noexcept;
+
+ //==============================================================================
+ /** Returns a subsection of the string.
+
+ If the range specified is beyond the limits of the string, as much as
+ possible is returned.
+
+ @param startIndex the index of the start of the substring needed
+ @param endIndex all characters from startIndex up to (but not including)
+ this index are returned
+ @see fromFirstOccurrenceOf, dropLastCharacters, getLastCharacters, upToFirstOccurrenceOf
+ */
+ String substring (int startIndex, int endIndex) const;
+
+ /** Returns a section of the string, starting from a given position.
+
+ @param startIndex the first character to include. If this is beyond the end
+ of the string, an empty string is returned. If it is zero or
+ less, the whole string is returned.
+ @returns the substring from startIndex up to the end of the string
+ @see dropLastCharacters, getLastCharacters, fromFirstOccurrenceOf, upToFirstOccurrenceOf, fromLastOccurrenceOf
+ */
+ String substring (int startIndex) const;
+
+ /** Returns a version of this string with a number of characters removed
+ from the end.
+
+ @param numberToDrop the number of characters to drop from the end of the
+ string. If this is greater than the length of the string,
+ an empty string will be returned. If zero or less, the
+ original string will be returned.
+ @see substring, fromFirstOccurrenceOf, upToFirstOccurrenceOf, fromLastOccurrenceOf, getLastCharacter
+ */
+ String dropLastCharacters (int numberToDrop) const;
+
+ /** Returns a number of characters from the end of the string.
+
+ This returns the last numCharacters characters from the end of the string. If the
+ string is shorter than numCharacters, the whole string is returned.
+
+ @see substring, dropLastCharacters, getLastCharacter
+ */
+ String getLastCharacters (int numCharacters) const;
+
+ //==============================================================================
+ /** Returns a section of the string starting from a given substring.
+
+ This will search for the first occurrence of the given substring, and
+ return the section of the string starting from the point where this is
+ found (optionally not including the substring itself).
+
+ e.g. for the string "123456", fromFirstOccurrenceOf ("34", true) would return "3456", and
+ fromFirstOccurrenceOf ("34", false) would return "56".
+
+ If the substring isn't found, the method will return an empty string.
+
+ If ignoreCase is true, the comparison will be case-insensitive.
+
+ @see upToFirstOccurrenceOf, fromLastOccurrenceOf
+ */
+ String fromFirstOccurrenceOf (StringRef substringToStartFrom,
+ bool includeSubStringInResult,
+ bool ignoreCase) const;
+
+ /** Returns a section of the string starting from the last occurrence of a given substring.
+
+ Similar to fromFirstOccurrenceOf(), but using the last occurrence of the substring, and
+ unlike fromFirstOccurrenceOf(), if the substring isn't found, this method will
+ return the whole of the original string.
+
+ @see fromFirstOccurrenceOf, upToLastOccurrenceOf
+ */
+ String fromLastOccurrenceOf (StringRef substringToFind,
+ bool includeSubStringInResult,
+ bool ignoreCase) const;
+
+ /** Returns the start of this string, up to the first occurrence of a substring.
+
+ This will search for the first occurrence of a given substring, and then
+ return a copy of the string, up to the position of this substring,
+ optionally including or excluding the substring itself in the result.
+
+ e.g. for the string "123456", upTo ("34", false) would return "12", and
+ upTo ("34", true) would return "1234".
+
+ If the substring isn't found, this will return the whole of the original string.
+
+ @see upToLastOccurrenceOf, fromFirstOccurrenceOf
+ */
+ String upToFirstOccurrenceOf (StringRef substringToEndWith,
+ bool includeSubStringInResult,
+ bool ignoreCase) const;
+
+ /** Returns the start of this string, up to the last occurrence of a substring.
+
+ Similar to upToFirstOccurrenceOf(), but this finds the last occurrence rather than the first.
+ If the substring isn't found, this will return the whole of the original string.
+
+ @see upToFirstOccurrenceOf, fromFirstOccurrenceOf
+ */
+ String upToLastOccurrenceOf (StringRef substringToFind,
+ bool includeSubStringInResult,
+ bool ignoreCase) const;
+
+ //==============================================================================
+ /** Returns a copy of this string with any whitespace characters removed from the start and end. */
+ String trim() const;
+
+ /** Returns a copy of this string with any whitespace characters removed from the start. */
+ String trimStart() const;
+
+ /** Returns a copy of this string with any whitespace characters removed from the end. */
+ String trimEnd() const;
+
+ /** Returns a copy of this string, having removed a specified set of characters from its start.
+ Characters are removed from the start of the string until it finds one that is not in the
+ specified set, and then it stops.
+ @param charactersToTrim the set of characters to remove.
+ @see trim, trimStart, trimCharactersAtEnd
+ */
+ String trimCharactersAtStart (StringRef charactersToTrim) const;
+
+ /** Returns a copy of this string, having removed a specified set of characters from its end.
+ Characters are removed from the end of the string until it finds one that is not in the
+ specified set, and then it stops.
+ @param charactersToTrim the set of characters to remove.
+ @see trim, trimEnd, trimCharactersAtStart
+ */
+ String trimCharactersAtEnd (StringRef charactersToTrim) const;
+
+ //==============================================================================
+ /** Returns an upper-case version of this string. */
+ String toUpperCase() const;
+
+ /** Returns an lower-case version of this string. */
+ String toLowerCase() const;
+
+ //==============================================================================
+ /** Replaces a sub-section of the string with another string.
+
+ This will return a copy of this string, with a set of characters
+ from startIndex to startIndex + numCharsToReplace removed, and with
+ a new string inserted in their place.
+
+ Note that this is a const method, and won't alter the string itself.
+
+ @param startIndex the first character to remove. If this is beyond the bounds of the string,
+ it will be constrained to a valid range.
+ @param numCharactersToReplace the number of characters to remove. If zero or less, no
+ characters will be taken out.
+ @param stringToInsert the new string to insert at startIndex after the characters have been
+ removed.
+ */
+ String replaceSection (int startIndex,
+ int numCharactersToReplace,
+ StringRef stringToInsert) const;
+
+ /** Replaces all occurrences of a substring with another string.
+
+ Returns a copy of this string, with any occurrences of stringToReplace
+ swapped for stringToInsertInstead.
+
+ Note that this is a const method, and won't alter the string itself.
+ */
+ String replace (StringRef stringToReplace,
+ StringRef stringToInsertInstead,
+ bool ignoreCase = false) const;
+
+ /** Returns a string with all occurrences of a character replaced with a different one. */
+ String replaceCharacter (juce_wchar characterToReplace,
+ juce_wchar characterToInsertInstead) const;
+
+ /** Replaces a set of characters with another set.
+
+ Returns a string in which each character from charactersToReplace has been replaced
+ by the character at the equivalent position in newCharacters (so the two strings
+ passed in must be the same length).
+
+ e.g. replaceCharacters ("abc", "def") replaces 'a' with 'd', 'b' with 'e', etc.
+
+ Note that this is a const method, and won't affect the string itself.
+ */
+ String replaceCharacters (StringRef charactersToReplace,
+ StringRef charactersToInsertInstead) const;
+
+ /** Returns a version of this string that only retains a fixed set of characters.
+
+ This will return a copy of this string, omitting any characters which are not
+ found in the string passed-in.
+
+ e.g. for "1122334455", retainCharacters ("432") would return "223344"
+
+ Note that this is a const method, and won't alter the string itself.
+ */
+ String retainCharacters (StringRef charactersToRetain) const;
+
+ /** Returns a version of this string with a set of characters removed.
+
+ This will return a copy of this string, omitting any characters which are
+ found in the string passed-in.
+
+ e.g. for "1122334455", removeCharacters ("432") would return "1155"
+
+ Note that this is a const method, and won't alter the string itself.
+ */
+ String removeCharacters (StringRef charactersToRemove) const;
+
+ /** Returns a section from the start of the string that only contains a certain set of characters.
+
+ This returns the leftmost section of the string, up to (and not including) the
+ first character that doesn't appear in the string passed in.
+ */
+ String initialSectionContainingOnly (StringRef permittedCharacters) const;
+
+ /** Returns a section from the start of the string that only contains a certain set of characters.
+
+ This returns the leftmost section of the string, up to (and not including) the
+ first character that occurs in the string passed in. (If none of the specified
+ characters are found in the string, the return value will just be the original string).
+ */
+ String initialSectionNotContaining (StringRef charactersToStopAt) const;
+
+ //==============================================================================
+ /** Checks whether the string might be in quotation marks.
+
+ @returns true if the string begins with a quote character (either a double or single quote).
+ It is also true if there is whitespace before the quote, but it doesn't check the end of the string.
+ @see unquoted, quoted
+ */
+ bool isQuotedString() const;
+
+ /** Removes quotation marks from around the string, (if there are any).
+
+ Returns a copy of this string with any quotes removed from its ends. Quotes that aren't
+ at the ends of the string are not affected. If there aren't any quotes, the original string
+ is returned.
+
+ Note that this is a const method, and won't alter the string itself.
+
+ @see isQuotedString, quoted
+ */
+ String unquoted() const;
+
+ /** Adds quotation marks around a string.
+
+ This will return a copy of the string with a quote at the start and end, (but won't
+ add the quote if there's already one there, so it's safe to call this on strings that
+ may already have quotes around them).
+
+ Note that this is a const method, and won't alter the string itself.
+
+ @param quoteCharacter the character to add at the start and end
+ @see isQuotedString, unquoted
+ */
+ String quoted (juce_wchar quoteCharacter = '"') const;
+
+
+ //==============================================================================
+ /** Creates a string which is a version of a string repeated and joined together.
+
+ @param stringToRepeat the string to repeat
+ @param numberOfTimesToRepeat how many times to repeat it
+ */
+ static String repeatedString (StringRef stringToRepeat,
+ int numberOfTimesToRepeat);
+
+ /** Returns a copy of this string with the specified character repeatedly added to its
+ beginning until the total length is at least the minimum length specified.
+ */
+ String paddedLeft (juce_wchar padCharacter, int minimumLength) const;
+
+ /** Returns a copy of this string with the specified character repeatedly added to its
+ end until the total length is at least the minimum length specified.
+ */
+ String paddedRight (juce_wchar padCharacter, int minimumLength) const;
+
+ /** Creates a string from data in an unknown format.
+
+ This looks at some binary data and tries to guess whether it's Unicode
+ or 8-bit characters, then returns a string that represents it correctly.
+
+ Should be able to handle Unicode endianness correctly, by looking at
+ the first two bytes.
+ */
+ static String createStringFromData (const void* data, int size);
+
+ /** Creates a String from a printf-style parameter list.
+
+ I don't like this method. I don't use it myself, and I recommend avoiding it and
+ using the operator<< methods or pretty much anything else instead. It's only provided
+ here because of the popular unrest that was stirred-up when I tried to remove it...
+
+ If you're really determined to use it, at least make sure that you never, ever,
+ pass any String objects to it as parameters. And bear in mind that internally, depending
+ on the platform, it may be using wchar_t or char character types, so that even string
+ literals can't be safely used as parameters if you're writing portable code.
+ */
+ static String formatted (const String formatString, ... );
+
+ //==============================================================================
+ // Numeric conversions..
+
+ /** Creates a string containing this signed 32-bit integer as a decimal number.
+ @see getIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (int decimalInteger);
+
+ /** Creates a string containing this unsigned 32-bit integer as a decimal number.
+ @see getIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (unsigned int decimalInteger);
+
+ /** Creates a string containing this signed 16-bit integer as a decimal number.
+ @see getIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (short decimalInteger);
+
+ /** Creates a string containing this unsigned 16-bit integer as a decimal number.
+ @see getIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (unsigned short decimalInteger);
+
+ /** Creates a string containing this signed 64-bit integer as a decimal number.
+ @see getLargeIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (int64 largeIntegerValue);
+
+ /** Creates a string containing this unsigned 64-bit integer as a decimal number.
+ @see getLargeIntValue, getFloatValue, getDoubleValue, toHexString
+ */
+ explicit String (uint64 largeIntegerValue);
+
+ /** Creates a string representing this floating-point number.
+ @param floatValue the value to convert to a string
+ @see getDoubleValue, getIntValue
+ */
+ explicit String (float floatValue);
+
+ /** Creates a string representing this floating-point number.
+ @param doubleValue the value to convert to a string
+ @see getFloatValue, getIntValue
+ */
+ explicit String (double doubleValue);
+
+ /** Creates a string representing this floating-point number.
+ @param floatValue the value to convert to a string
+ @param numberOfDecimalPlaces if this is > 0, it will format the number using that many
+ decimal places, and will not use exponent notation. If 0 or
+ less, it will use exponent notation if necessary.
+ @see getDoubleValue, getIntValue
+ */
+ String (float floatValue, int numberOfDecimalPlaces);
+
+ /** Creates a string representing this floating-point number.
+ @param doubleValue the value to convert to a string
+ @param numberOfDecimalPlaces if this is > 0, it will format the number using that many
+ decimal places, and will not use exponent notation. If 0 or
+ less, it will use exponent notation if necessary.
+ @see getFloatValue, getIntValue
+ */
+ String (double doubleValue, int numberOfDecimalPlaces);
+
+ /** Reads the value of the string as a decimal number (up to 32 bits in size).
+
+ @returns the value of the string as a 32 bit signed base-10 integer.
+ @see getTrailingIntValue, getHexValue32, getHexValue64
+ */
+ int getIntValue() const noexcept;
+
+ /** Reads the value of the string as a decimal number (up to 64 bits in size).
+ @returns the value of the string as a 64 bit signed base-10 integer.
+ */
+ int64 getLargeIntValue() const noexcept;
+
+ /** Parses a decimal number from the end of the string.
+
+ This will look for a value at the end of the string.
+ e.g. for "321 xyz654" it will return 654; for "2 3 4" it'll return 4.
+
+ Negative numbers are not handled, so "xyz-5" returns 5.
+
+ @see getIntValue
+ */
+ int getTrailingIntValue() const noexcept;
+
+ /** Parses this string as a floating point number.
+
+ @returns the value of the string as a 32-bit floating point value.
+ @see getDoubleValue
+ */
+ float getFloatValue() const noexcept;
+
+ /** Parses this string as a floating point number.
+
+ @returns the value of the string as a 64-bit floating point value.
+ @see getFloatValue
+ */
+ double getDoubleValue() const noexcept;
+
+ /** Parses the string as a hexadecimal number.
+
+ Non-hexadecimal characters in the string are ignored.
+
+ If the string contains too many characters, then the lowest significant
+ digits are returned, e.g. "ffff12345678" would produce 0x12345678.
+
+ @returns a 32-bit number which is the value of the string in hex.
+ */
+ int getHexValue32() const noexcept;
+
+ /** Parses the string as a hexadecimal number.
+
+ Non-hexadecimal characters in the string are ignored.
+
+ If the string contains too many characters, then the lowest significant
+ digits are returned, e.g. "ffff1234567812345678" would produce 0x1234567812345678.
+
+ @returns a 64-bit number which is the value of the string in hex.
+ */
+ int64 getHexValue64() const noexcept;
+
+ /** Creates a string representing this 32-bit value in hexadecimal. */
+ static String toHexString (int number);
+
+ /** Creates a string representing this 64-bit value in hexadecimal. */
+ static String toHexString (int64 number);
+
+ /** Creates a string representing this 16-bit value in hexadecimal. */
+ static String toHexString (short number);
+
+ /** Creates a string containing a hex dump of a block of binary data.
+
+ @param data the binary data to use as input
+ @param size how many bytes of data to use
+ @param groupSize how many bytes are grouped together before inserting a
+ space into the output. e.g. group size 0 has no spaces,
+ group size 1 looks like: "be a1 c2 ff", group size 2 looks
+ like "bea1 c2ff".
+ */
+ static String toHexString (const void* data, int size, int groupSize = 1);
+
+ //==============================================================================
+ /** Returns the character pointer currently being used to store this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+ */
+ inline CharPointerType getCharPointer() const noexcept { return text; }
+
+ /** Returns a pointer to a UTF-8 version of this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+
+ To find out how many bytes you need to store this string as UTF-8, you can call
+ CharPointer_UTF8::getBytesRequiredFor (myString.getCharPointer())
+
+ @see toRawUTF8, getCharPointer, toUTF16, toUTF32
+ */
+ CharPointer_UTF8 toUTF8() const;
+
+ /** Returns a pointer to a UTF-8 version of this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+
+ To find out how many bytes you need to store this string as UTF-8, you can call
+ CharPointer_UTF8::getBytesRequiredFor (myString.getCharPointer())
+
+ @see getCharPointer, toUTF8, toUTF16, toUTF32
+ */
+ const char* toRawUTF8() const;
+
+ /** Returns a pointer to a UTF-16 version of this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+
+ To find out how many bytes you need to store this string as UTF-16, you can call
+ CharPointer_UTF16::getBytesRequiredFor (myString.getCharPointer())
+
+ @see getCharPointer, toUTF8, toUTF32
+ */
+ CharPointer_UTF16 toUTF16() const;
+
+ /** Returns a pointer to a UTF-32 version of this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+
+ @see getCharPointer, toUTF8, toUTF16
+ */
+ CharPointer_UTF32 toUTF32() const;
+
+ /** Returns a pointer to a wchar_t version of this string.
+
+ Because it returns a reference to the string's internal data, the pointer
+ that is returned must not be stored anywhere, as it can be deleted whenever the
+ string changes.
+
+ Bear in mind that the wchar_t type is different on different platforms, so on
+ Windows, this will be equivalent to calling toUTF16(), on unix it'll be the same
+ as calling toUTF32(), etc.
+
+ @see getCharPointer, toUTF8, toUTF16, toUTF32
+ */
+ const wchar_t* toWideCharPointer() const;
+
+ /** */
+ std::string toStdString() const;
+
+ //==============================================================================
+ /** Creates a String from a UTF-8 encoded buffer.
+ If the size is < 0, it'll keep reading until it hits a zero.
+ */
+ static String fromUTF8 (const char* utf8buffer, int bufferSizeBytes = -1);
+
+ /** Returns the number of bytes required to represent this string as UTF8.
+ The number returned does NOT include the trailing zero.
+ @see toUTF8, copyToUTF8
+ */
+ size_t getNumBytesAsUTF8() const noexcept;
+
+ //==============================================================================
+ /** Copies the string to a buffer as UTF-8 characters.
+
+ Returns the number of bytes copied to the buffer, including the terminating null
+ character.
+
+ To find out how many bytes you need to store this string as UTF-8, you can call
+ CharPointer_UTF8::getBytesRequiredFor (myString.getCharPointer())
+
+ @param destBuffer the place to copy it to; if this is a null pointer, the method just
+ returns the number of bytes required (including the terminating null character).
+ @param maxBufferSizeBytes the size of the destination buffer, in bytes. If the string won't fit, it'll
+ put in as many as it can while still allowing for a terminating null char at the
+ end, and will return the number of bytes that were actually used.
+ @see CharPointer_UTF8::writeWithDestByteLimit
+ */
+ size_t copyToUTF8 (CharPointer_UTF8::CharType* destBuffer, size_t maxBufferSizeBytes) const noexcept;
+
+ /** Copies the string to a buffer as UTF-16 characters.
+
+ Returns the number of bytes copied to the buffer, including the terminating null
+ character.
+
+ To find out how many bytes you need to store this string as UTF-16, you can call
+ CharPointer_UTF16::getBytesRequiredFor (myString.getCharPointer())
+
+ @param destBuffer the place to copy it to; if this is a null pointer, the method just
+ returns the number of bytes required (including the terminating null character).
+ @param maxBufferSizeBytes the size of the destination buffer, in bytes. If the string won't fit, it'll
+ put in as many as it can while still allowing for a terminating null char at the
+ end, and will return the number of bytes that were actually used.
+ @see CharPointer_UTF16::writeWithDestByteLimit
+ */
+ size_t copyToUTF16 (CharPointer_UTF16::CharType* destBuffer, size_t maxBufferSizeBytes) const noexcept;
+
+ /** Copies the string to a buffer as UTF-32 characters.
+
+ Returns the number of bytes copied to the buffer, including the terminating null
+ character.
+
+ To find out how many bytes you need to store this string as UTF-32, you can call
+ CharPointer_UTF32::getBytesRequiredFor (myString.getCharPointer())
+
+ @param destBuffer the place to copy it to; if this is a null pointer, the method just
+ returns the number of bytes required (including the terminating null character).
+ @param maxBufferSizeBytes the size of the destination buffer, in bytes. If the string won't fit, it'll
+ put in as many as it can while still allowing for a terminating null char at the
+ end, and will return the number of bytes that were actually used.
+ @see CharPointer_UTF32::writeWithDestByteLimit
+ */
+ size_t copyToUTF32 (CharPointer_UTF32::CharType* destBuffer, size_t maxBufferSizeBytes) const noexcept;
+
+ //==============================================================================
+ /** Increases the string's internally allocated storage.
+
+ Although the string's contents won't be affected by this call, it will
+ increase the amount of memory allocated internally for the string to grow into.
+
+ If you're about to make a large number of calls to methods such
+ as += or <<, it's more efficient to preallocate enough extra space
+ beforehand, so that these methods won't have to keep resizing the string
+ to append the extra characters.
+
+ @param numBytesNeeded the number of bytes to allocate storage for. If this
+ value is less than the currently allocated size, it will
+ have no effect.
+ */
+ void preallocateBytes (size_t numBytesNeeded);
+
+ /** Swaps the contents of this string with another one.
+ This is a very fast operation, as no allocation or copying needs to be done.
+ */
+ void swapWith (String& other) noexcept;
+
+ //==============================================================================
+ #if JUCE_MAC || JUCE_IOS || DOXYGEN
+ /** MAC ONLY - Creates a String from an OSX CFString. */
+ static String fromCFString (CFStringRef cfString);
+
+ /** MAC ONLY - Converts this string to a CFString.
+ Remember that you must use CFRelease() to free the returned string when you're
+ finished with it.
+ */
+ CFStringRef toCFString() const;
+
+ /** MAC ONLY - Returns a copy of this string in which any decomposed unicode characters have
+ been converted to their precomposed equivalents. */
+ String convertToPrecomposedUnicode() const;
+ #endif
+
+ /** Returns the number of String objects which are currently sharing the same internal
+ data as this one.
+ */
+ int getReferenceCount() const noexcept;
+
+private:
+ //==============================================================================
+ CharPointerType text;
+
+ //==============================================================================
+ struct PreallocationBytes
+ {
+ explicit PreallocationBytes (size_t) noexcept;
+ size_t numBytes;
+ };
+
+ explicit String (const PreallocationBytes&); // This constructor preallocates a certain amount of memory
+ size_t getByteOffsetOfEnd() const noexcept;
+ JUCE_DEPRECATED (String (const String&, size_t));
+
+ // This private cast operator should prevent strings being accidentally cast
+ // to bools (this is possible because the compiler can add an implicit cast
+ // via a const char*)
+ operator bool() const noexcept { return false; }
+};
+
+//==============================================================================
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (const char* string1, const String& string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (const wchar_t* string1, const String& string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (char string1, const String& string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (wchar_t string1, const String& string2);
+#if ! JUCE_NATIVE_WCHAR_IS_UTF32
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (juce_wchar string1, const String& string2);
+#endif
+
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, const String& string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, const char* string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, const wchar_t* string2);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, char characterToAppend);
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, wchar_t characterToAppend);
+#if ! JUCE_NATIVE_WCHAR_IS_UTF32
+/** Concatenates two strings. */
+JUCE_API String JUCE_CALLTYPE operator+ (String string1, juce_wchar characterToAppend);
+#endif
+
+//==============================================================================
+/** Appends a character at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, char characterToAppend);
+/** Appends a character at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, wchar_t characterToAppend);
+#if ! JUCE_NATIVE_WCHAR_IS_UTF32
+/** Appends a character at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, juce_wchar characterToAppend);
+#endif
+
+/** Appends a string to the end of the first one. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const char* string2);
+/** Appends a string to the end of the first one. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const wchar_t* string2);
+/** Appends a string to the end of the first one. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const String& string2);
+
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, short number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, long number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int64 number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, uint64 number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, float number);
+/** Appends a decimal number at the end of a string. */
+JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, double number);
+
+//==============================================================================
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const String& string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const char* string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const wchar_t* string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const CharPointer_UTF8 string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const CharPointer_UTF16 string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, const CharPointer_UTF32 string2) noexcept;
+
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const String& string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const char* string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const wchar_t* string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const CharPointer_UTF8 string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const CharPointer_UTF16 string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, const CharPointer_UTF32 string2) noexcept;
+
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator> (const String& string1, const String& string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator< (const String& string1, const String& string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator>= (const String& string1, const String& string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator<= (const String& string1, const String& string2) noexcept;
+
+//==============================================================================
+/** This operator allows you to write a juce String directly to std output streams.
+ This is handy for writing strings to std::cout, std::cerr, etc.
+*/
+template <class traits>
+std::basic_ostream <char, traits>& JUCE_CALLTYPE operator<< (std::basic_ostream <char, traits>& stream, const String& stringToWrite)
+{
+ return stream << stringToWrite.toRawUTF8();
+}
+
+/** This operator allows you to write a juce String directly to std output streams.
+ This is handy for writing strings to std::wcout, std::wcerr, etc.
+*/
+template <class traits>
+std::basic_ostream <wchar_t, traits>& JUCE_CALLTYPE operator<< (std::basic_ostream <wchar_t, traits>& stream, const String& stringToWrite)
+{
+ return stream << stringToWrite.toWideCharPointer();
+}
+
+/** Writes a string to an OutputStream as UTF8. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& stringToWrite);
+
+/** Writes a string to an OutputStream as UTF8. */
+JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, StringRef stringToWrite);
+
+
+#endif // JUCE_STRING_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.cpp
new file mode 100644
index 0000000..6c49138
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.cpp
@@ -0,0 +1,485 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+StringArray::StringArray() noexcept
+{
+}
+
+StringArray::StringArray (const StringArray& other)
+ : strings (other.strings)
+{
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+StringArray::StringArray (StringArray&& other) noexcept
+ : strings (static_cast <Array <String>&&> (other.strings))
+{
+}
+#endif
+
+StringArray::StringArray (const String& firstValue)
+{
+ strings.add (firstValue);
+}
+
+StringArray::StringArray (const String* initialStrings, int numberOfStrings)
+{
+ strings.addArray (initialStrings, numberOfStrings);
+}
+
+StringArray::StringArray (const char* const* initialStrings)
+{
+ strings.addNullTerminatedArray (initialStrings);
+}
+
+StringArray::StringArray (const char* const* initialStrings, int numberOfStrings)
+{
+ strings.addArray (initialStrings, numberOfStrings);
+}
+
+StringArray::StringArray (const wchar_t* const* initialStrings)
+{
+ strings.addNullTerminatedArray (initialStrings);
+}
+
+StringArray::StringArray (const wchar_t* const* initialStrings, int numberOfStrings)
+{
+ strings.addArray (initialStrings, numberOfStrings);
+}
+
+StringArray& StringArray::operator= (const StringArray& other)
+{
+ strings = other.strings;
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+StringArray& StringArray::operator= (StringArray&& other) noexcept
+{
+ strings = static_cast <Array<String>&&> (other.strings);
+ return *this;
+}
+#endif
+
+StringArray::~StringArray()
+{
+}
+
+bool StringArray::operator== (const StringArray& other) const noexcept
+{
+ return strings == other.strings;
+}
+
+bool StringArray::operator!= (const StringArray& other) const noexcept
+{
+ return ! operator== (other);
+}
+
+void StringArray::swapWith (StringArray& other) noexcept
+{
+ strings.swapWith (other.strings);
+}
+
+void StringArray::clear()
+{
+ strings.clear();
+}
+
+void StringArray::clearQuick()
+{
+ strings.clearQuick();
+}
+
+const String& StringArray::operator[] (const int index) const noexcept
+{
+ if (isPositiveAndBelow (index, strings.size()))
+ return strings.getReference (index);
+
+ return String::empty;
+}
+
+String& StringArray::getReference (const int index) noexcept
+{
+ return strings.getReference (index);
+}
+
+void StringArray::add (const String& newString)
+{
+ strings.add (newString);
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+void StringArray::add (String&& stringToAdd)
+{
+ strings.add (static_cast<String&&> (stringToAdd));
+}
+#endif
+
+void StringArray::insert (const int index, const String& newString)
+{
+ strings.insert (index, newString);
+}
+
+void StringArray::addIfNotAlreadyThere (const String& newString, const bool ignoreCase)
+{
+ if (! contains (newString, ignoreCase))
+ add (newString);
+}
+
+void StringArray::addArray (const StringArray& otherArray, int startIndex, int numElementsToAdd)
+{
+ if (startIndex < 0)
+ {
+ jassertfalse;
+ startIndex = 0;
+ }
+
+ if (numElementsToAdd < 0 || startIndex + numElementsToAdd > otherArray.size())
+ numElementsToAdd = otherArray.size() - startIndex;
+
+ while (--numElementsToAdd >= 0)
+ strings.add (otherArray.strings.getReference (startIndex++));
+}
+
+void StringArray::set (const int index, const String& newString)
+{
+ strings.set (index, newString);
+}
+
+bool StringArray::contains (StringRef stringToLookFor, const bool ignoreCase) const
+{
+ return indexOf (stringToLookFor, ignoreCase) >= 0;
+}
+
+int StringArray::indexOf (StringRef stringToLookFor, const bool ignoreCase, int i) const
+{
+ if (i < 0)
+ i = 0;
+
+ const int numElements = size();
+
+ if (ignoreCase)
+ {
+ for (; i < numElements; ++i)
+ if (strings.getReference(i).equalsIgnoreCase (stringToLookFor))
+ return i;
+ }
+ else
+ {
+ for (; i < numElements; ++i)
+ if (stringToLookFor == strings.getReference (i))
+ return i;
+ }
+
+ return -1;
+}
+
+void StringArray::move (const int currentIndex, const int newIndex) noexcept
+{
+ strings.move (currentIndex, newIndex);
+}
+
+//==============================================================================
+void StringArray::remove (const int index)
+{
+ strings.remove (index);
+}
+
+void StringArray::removeString (StringRef stringToRemove, const bool ignoreCase)
+{
+ if (ignoreCase)
+ {
+ for (int i = size(); --i >= 0;)
+ if (strings.getReference(i).equalsIgnoreCase (stringToRemove))
+ strings.remove (i);
+ }
+ else
+ {
+ for (int i = size(); --i >= 0;)
+ if (stringToRemove == strings.getReference (i))
+ strings.remove (i);
+ }
+}
+
+void StringArray::removeRange (int startIndex, int numberToRemove)
+{
+ strings.removeRange (startIndex, numberToRemove);
+}
+
+//==============================================================================
+void StringArray::removeEmptyStrings (const bool removeWhitespaceStrings)
+{
+ if (removeWhitespaceStrings)
+ {
+ for (int i = size(); --i >= 0;)
+ if (! strings.getReference(i).containsNonWhitespaceChars())
+ strings.remove (i);
+ }
+ else
+ {
+ for (int i = size(); --i >= 0;)
+ if (strings.getReference(i).isEmpty())
+ strings.remove (i);
+ }
+}
+
+void StringArray::trim()
+{
+ for (int i = size(); --i >= 0;)
+ {
+ String& s = strings.getReference(i);
+ s = s.trim();
+ }
+}
+
+//==============================================================================
+struct InternalStringArrayComparator_CaseSensitive
+{
+ static int compareElements (String& s1, String& s2) noexcept { return s1.compare (s2); }
+};
+
+struct InternalStringArrayComparator_CaseInsensitive
+{
+ static int compareElements (String& s1, String& s2) noexcept { return s1.compareIgnoreCase (s2); }
+};
+
+struct InternalStringArrayComparator_Natural
+{
+ static int compareElements (String& s1, String& s2) noexcept { return s1.compareNatural (s2); }
+};
+
+void StringArray::sort (const bool ignoreCase)
+{
+ if (ignoreCase)
+ {
+ InternalStringArrayComparator_CaseInsensitive comp;
+ strings.sort (comp);
+ }
+ else
+ {
+ InternalStringArrayComparator_CaseSensitive comp;
+ strings.sort (comp);
+ }
+}
+
+void StringArray::sortNatural()
+{
+ InternalStringArrayComparator_Natural comp;
+ strings.sort (comp);
+}
+
+//==============================================================================
+String StringArray::joinIntoString (StringRef separator, int start, int numberToJoin) const
+{
+ const int last = (numberToJoin < 0) ? size()
+ : jmin (size(), start + numberToJoin);
+
+ if (start < 0)
+ start = 0;
+
+ if (start >= last)
+ return String();
+
+ if (start == last - 1)
+ return strings.getReference (start);
+
+ const size_t separatorBytes = separator.text.sizeInBytes() - sizeof (String::CharPointerType::CharType);
+ size_t bytesNeeded = separatorBytes * (size_t) (last - start - 1);
+
+ for (int i = start; i < last; ++i)
+ bytesNeeded += strings.getReference(i).getCharPointer().sizeInBytes() - sizeof (String::CharPointerType::CharType);
+
+ String result;
+ result.preallocateBytes (bytesNeeded);
+
+ String::CharPointerType dest (result.getCharPointer());
+
+ while (start < last)
+ {
+ const String& s = strings.getReference (start);
+
+ if (! s.isEmpty())
+ dest.writeAll (s.getCharPointer());
+
+ if (++start < last && separatorBytes > 0)
+ dest.writeAll (separator.text);
+ }
+
+ dest.writeNull();
+
+ return result;
+}
+
+int StringArray::addTokens (StringRef text, const bool preserveQuotedStrings)
+{
+ return addTokens (text, " \n\r\t", preserveQuotedStrings ? "\"" : "");
+}
+
+int StringArray::addTokens (StringRef text, StringRef breakCharacters, StringRef quoteCharacters)
+{
+ int num = 0;
+
+ if (text.isNotEmpty())
+ {
+ for (String::CharPointerType t (text.text);;)
+ {
+ String::CharPointerType tokenEnd (CharacterFunctions::findEndOfToken (t,
+ breakCharacters.text,
+ quoteCharacters.text));
+ strings.add (String (t, tokenEnd));
+ ++num;
+
+ if (tokenEnd.isEmpty())
+ break;
+
+ t = ++tokenEnd;
+ }
+ }
+
+ return num;
+}
+
+int StringArray::addLines (StringRef sourceText)
+{
+ int numLines = 0;
+ String::CharPointerType text (sourceText.text);
+ bool finished = text.isEmpty();
+
+ while (! finished)
+ {
+ for (String::CharPointerType startOfLine (text);;)
+ {
+ const String::CharPointerType endOfLine (text);
+
+ switch (text.getAndAdvance())
+ {
+ case 0: finished = true; break;
+ case '\n': break;
+ case '\r': if (*text == '\n') ++text; break;
+ default: continue;
+ }
+
+ strings.add (String (startOfLine, endOfLine));
+ ++numLines;
+ break;
+ }
+ }
+
+ return numLines;
+}
+
+StringArray StringArray::fromTokens (StringRef stringToTokenise, bool preserveQuotedStrings)
+{
+ StringArray s;
+ s.addTokens (stringToTokenise, preserveQuotedStrings);
+ return s;
+}
+
+StringArray StringArray::fromTokens (StringRef stringToTokenise,
+ StringRef breakCharacters,
+ StringRef quoteCharacters)
+{
+ StringArray s;
+ s.addTokens (stringToTokenise, breakCharacters, quoteCharacters);
+ return s;
+}
+
+StringArray StringArray::fromLines (StringRef stringToBreakUp)
+{
+ StringArray s;
+ s.addLines (stringToBreakUp);
+ return s;
+}
+
+//==============================================================================
+void StringArray::removeDuplicates (const bool ignoreCase)
+{
+ for (int i = 0; i < size() - 1; ++i)
+ {
+ const String s (strings.getReference(i));
+
+ for (int nextIndex = i + 1;;)
+ {
+ nextIndex = indexOf (s, ignoreCase, nextIndex);
+
+ if (nextIndex < 0)
+ break;
+
+ strings.remove (nextIndex);
+ }
+ }
+}
+
+void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
+ const bool appendNumberToFirstInstance,
+ CharPointer_UTF8 preNumberString,
+ CharPointer_UTF8 postNumberString)
+{
+ CharPointer_UTF8 defaultPre (" ("), defaultPost (")");
+
+ if (preNumberString.getAddress() == nullptr)
+ preNumberString = defaultPre;
+
+ if (postNumberString.getAddress() == nullptr)
+ postNumberString = defaultPost;
+
+ for (int i = 0; i < size() - 1; ++i)
+ {
+ String& s = strings.getReference(i);
+
+ int nextIndex = indexOf (s, ignoreCase, i + 1);
+
+ if (nextIndex >= 0)
+ {
+ const String original (s);
+
+ int number = 0;
+
+ if (appendNumberToFirstInstance)
+ s = original + String (preNumberString) + String (++number) + String (postNumberString);
+ else
+ ++number;
+
+ while (nextIndex >= 0)
+ {
+ set (nextIndex, (*this)[nextIndex] + String (preNumberString) + String (++number) + String (postNumberString));
+ nextIndex = indexOf (original, ignoreCase, nextIndex + 1);
+ }
+ }
+ }
+}
+
+void StringArray::ensureStorageAllocated (int minNumElements)
+{
+ strings.ensureStorageAllocated (minNumElements);
+}
+
+void StringArray::minimiseStorageOverheads()
+{
+ strings.minimiseStorageOverheads();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.h
new file mode 100644
index 0000000..52335e1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringArray.h
@@ -0,0 +1,421 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STRINGARRAY_H_INCLUDED
+#define JUCE_STRINGARRAY_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A special array for holding a list of strings.
+
+ @see String, StringPairArray
+*/
+class JUCE_API StringArray
+{
+public:
+ //==============================================================================
+ /** Creates an empty string array */
+ StringArray() noexcept;
+
+ /** Creates a copy of another string array */
+ StringArray (const StringArray&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ StringArray (StringArray&&) noexcept;
+ #endif
+
+ /** Creates an array containing a single string. */
+ explicit StringArray (const String& firstValue);
+
+ /** Creates an array from a raw array of strings.
+ @param strings an array of strings to add
+ @param numberOfStrings how many items there are in the array
+ */
+ StringArray (const String* strings, int numberOfStrings);
+
+ /** Creates a copy of an array of string literals.
+ @param strings an array of strings to add. Null pointers in the array will be
+ treated as empty strings
+ @param numberOfStrings how many items there are in the array
+ */
+ StringArray (const char* const* strings, int numberOfStrings);
+
+ /** Creates a copy of a null-terminated array of string literals.
+
+ Each item from the array passed-in is added, until it encounters a null pointer,
+ at which point it stops.
+ */
+ explicit StringArray (const char* const* strings);
+
+ /** Creates a copy of a null-terminated array of string literals.
+ Each item from the array passed-in is added, until it encounters a null pointer,
+ at which point it stops.
+ */
+ explicit StringArray (const wchar_t* const* strings);
+
+ /** Creates a copy of an array of string literals.
+ @param strings an array of strings to add. Null pointers in the array will be
+ treated as empty strings
+ @param numberOfStrings how many items there are in the array
+ */
+ StringArray (const wchar_t* const* strings, int numberOfStrings);
+
+ /** Destructor. */
+ ~StringArray();
+
+ /** Copies the contents of another string array into this one */
+ StringArray& operator= (const StringArray&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ StringArray& operator= (StringArray&&) noexcept;
+ #endif
+
+ /** Swaps the contents of this and another StringArray. */
+ void swapWith (StringArray&) noexcept;
+
+ //==============================================================================
+ /** Compares two arrays.
+ Comparisons are case-sensitive.
+ @returns true only if the other array contains exactly the same strings in the same order
+ */
+ bool operator== (const StringArray&) const noexcept;
+
+ /** Compares two arrays.
+ Comparisons are case-sensitive.
+ @returns false if the other array contains exactly the same strings in the same order
+ */
+ bool operator!= (const StringArray&) const noexcept;
+
+ //==============================================================================
+ /** Returns the number of strings in the array */
+ inline int size() const noexcept { return strings.size(); };
+
+ /** Returns one of the strings from the array.
+
+ If the index is out-of-range, an empty string is returned.
+
+ Obviously the reference returned shouldn't be stored for later use, as the
+ string it refers to may disappear when the array changes.
+ */
+ const String& operator[] (int index) const noexcept;
+
+ /** Returns a reference to one of the strings in the array.
+ This lets you modify a string in-place in the array, but you must be sure that
+ the index is in-range.
+ */
+ String& getReference (int index) noexcept;
+
+ /** Returns a pointer to the first String in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline String* begin() const noexcept { return strings.begin(); }
+
+ /** Returns a pointer to the String which follows the last element in the array.
+ This method is provided for compatibility with standard C++ iteration mechanisms.
+ */
+ inline String* end() const noexcept { return strings.end(); }
+
+ /** Searches for a string in the array.
+
+ The comparison will be case-insensitive if the ignoreCase parameter is true.
+
+ @returns true if the string is found inside the array
+ */
+ bool contains (StringRef stringToLookFor,
+ bool ignoreCase = false) const;
+
+ /** Searches for a string in the array.
+
+ The comparison will be case-insensitive if the ignoreCase parameter is true.
+
+ @param stringToLookFor the string to try to find
+ @param ignoreCase whether the comparison should be case-insensitive
+ @param startIndex the first index to start searching from
+ @returns the index of the first occurrence of the string in this array,
+ or -1 if it isn't found.
+ */
+ int indexOf (StringRef stringToLookFor,
+ bool ignoreCase = false,
+ int startIndex = 0) const;
+
+ //==============================================================================
+ /** Appends a string at the end of the array. */
+ void add (const String& stringToAdd);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Appends a string at the end of the array. */
+ void add (String&& stringToAdd);
+ #endif
+
+ /** Inserts a string into the array.
+
+ This will insert a string into the array at the given index, moving
+ up the other elements to make room for it.
+ If the index is less than zero or greater than the size of the array,
+ the new string will be added to the end of the array.
+ */
+ void insert (int index, const String& stringToAdd);
+
+ /** Adds a string to the array as long as it's not already in there.
+ The search can optionally be case-insensitive.
+ */
+ void addIfNotAlreadyThere (const String& stringToAdd, bool ignoreCase = false);
+
+ /** Replaces one of the strings in the array with another one.
+
+ If the index is higher than the array's size, the new string will be
+ added to the end of the array; if it's less than zero nothing happens.
+ */
+ void set (int index, const String& newString);
+
+ /** Appends some strings from another array to the end of this one.
+
+ @param other the array to add
+ @param startIndex the first element of the other array to add
+ @param numElementsToAdd the maximum number of elements to add (if this is
+ less than zero, they are all added)
+ */
+ void addArray (const StringArray& other,
+ int startIndex = 0,
+ int numElementsToAdd = -1);
+
+ /** Breaks up a string into tokens and adds them to this array.
+
+ This will tokenise the given string using whitespace characters as the
+ token delimiters, and will add these tokens to the end of the array.
+ @returns the number of tokens added
+ @see fromTokens
+ */
+ int addTokens (StringRef stringToTokenise, bool preserveQuotedStrings);
+
+ /** Breaks up a string into tokens and adds them to this array.
+
+ This will tokenise the given string (using the string passed in to define the
+ token delimiters), and will add these tokens to the end of the array.
+
+ @param stringToTokenise the string to tokenise
+ @param breakCharacters a string of characters, any of which will be considered
+ to be a token delimiter.
+ @param quoteCharacters if this string isn't empty, it defines a set of characters
+ which are treated as quotes. Any text occurring
+ between quotes is not broken up into tokens.
+ @returns the number of tokens added
+ @see fromTokens
+ */
+ int addTokens (StringRef stringToTokenise,
+ StringRef breakCharacters,
+ StringRef quoteCharacters);
+
+ /** Breaks up a string into lines and adds them to this array.
+
+ This breaks a string down into lines separated by \\n or \\r\\n, and adds each line
+ to the array. Line-break characters are omitted from the strings that are added to
+ the array.
+ */
+ int addLines (StringRef stringToBreakUp);
+
+ /** Returns an array containing the tokens in a given string.
+
+ This will tokenise the given string using whitespace characters as the
+ token delimiters, and return these tokens as an array.
+ @see addTokens
+ */
+ static StringArray fromTokens (StringRef stringToTokenise,
+ bool preserveQuotedStrings);
+
+ /** Returns an array containing the tokens in a given string.
+
+ This will tokenise the given string using whitespace characters as the
+ token delimiters, and return these tokens as an array.
+
+ @param stringToTokenise the string to tokenise
+ @param breakCharacters a string of characters, any of which will be considered
+ to be a token delimiter.
+ @param quoteCharacters if this string isn't empty, it defines a set of characters
+ which are treated as quotes. Any text occurring
+ between quotes is not broken up into tokens.
+ @see addTokens
+ */
+ static StringArray fromTokens (StringRef stringToTokenise,
+ StringRef breakCharacters,
+ StringRef quoteCharacters);
+
+ /** Returns an array containing the lines in a given string.
+
+ This breaks a string down into lines separated by \\n or \\r\\n, and returns an
+ array containing these lines. Line-break characters are omitted from the strings that
+ are added to the array.
+ */
+ static StringArray fromLines (StringRef stringToBreakUp);
+
+ //==============================================================================
+ /** Removes all elements from the array. */
+ void clear();
+
+ /** Removes all elements from the array without freeing the array's allocated storage.
+ @see clear
+ */
+ void clearQuick();
+
+ /** Removes a string from the array.
+ If the index is out-of-range, no action will be taken.
+ */
+ void remove (int index);
+
+ /** Finds a string in the array and removes it.
+ This will remove the first occurrence of the given string from the array. The
+ comparison may be case-insensitive depending on the ignoreCase parameter.
+ */
+ void removeString (StringRef stringToRemove,
+ bool ignoreCase = false);
+
+ /** Removes a range of elements from the array.
+
+ This will remove a set of elements, starting from the given index,
+ and move subsequent elements down to close the gap.
+
+ If the range extends beyond the bounds of the array, it will
+ be safely clipped to the size of the array.
+
+ @param startIndex the index of the first element to remove
+ @param numberToRemove how many elements should be removed
+ */
+ void removeRange (int startIndex, int numberToRemove);
+
+ /** Removes any duplicated elements from the array.
+
+ If any string appears in the array more than once, only the first occurrence of
+ it will be retained.
+
+ @param ignoreCase whether to use a case-insensitive comparison
+ */
+ void removeDuplicates (bool ignoreCase);
+
+ /** Removes empty strings from the array.
+ @param removeWhitespaceStrings if true, strings that only contain whitespace
+ characters will also be removed
+ */
+ void removeEmptyStrings (bool removeWhitespaceStrings = true);
+
+ /** Moves one of the strings to a different position.
+
+ This will move the string to a specified index, shuffling along
+ any intervening elements as required.
+
+ So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
+ move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
+
+ @param currentIndex the index of the value to be moved. If this isn't a
+ valid index, then nothing will be done
+ @param newIndex the index at which you'd like this value to end up. If this
+ is less than zero, the value will be moved to the end
+ of the array
+ */
+ void move (int currentIndex, int newIndex) noexcept;
+
+ /** Deletes any whitespace characters from the starts and ends of all the strings. */
+ void trim();
+
+ /** Adds numbers to the strings in the array, to make each string unique.
+
+ This will add numbers to the ends of groups of similar strings.
+ e.g. if there are two "moose" strings, they will become "moose (1)" and "moose (2)"
+
+ @param ignoreCaseWhenComparing whether the comparison used is case-insensitive
+ @param appendNumberToFirstInstance whether the first of a group of similar strings
+ also has a number appended to it.
+ @param preNumberString when adding a number, this string is added before the number.
+ If you pass 0, a default string will be used, which adds
+ brackets around the number.
+ @param postNumberString this string is appended after any numbers that are added.
+ If you pass 0, a default string will be used, which adds
+ brackets around the number.
+ */
+ void appendNumbersToDuplicates (bool ignoreCaseWhenComparing,
+ bool appendNumberToFirstInstance,
+ CharPointer_UTF8 preNumberString = CharPointer_UTF8 (nullptr),
+ CharPointer_UTF8 postNumberString = CharPointer_UTF8 (nullptr));
+
+ //==============================================================================
+ /** Joins the strings in the array together into one string.
+
+ This will join a range of elements from the array into a string, separating
+ them with a given string.
+
+ e.g. joinIntoString (",") will turn an array of "a" "b" and "c" into "a,b,c".
+
+ @param separatorString the string to insert between all the strings
+ @param startIndex the first element to join
+ @param numberOfElements how many elements to join together. If this is less
+ than zero, all available elements will be used.
+ */
+ String joinIntoString (StringRef separatorString,
+ int startIndex = 0,
+ int numberOfElements = -1) const;
+
+ //==============================================================================
+ /** Sorts the array into alphabetical order.
+ @param ignoreCase if true, the comparisons used will be case-sensitive.
+ */
+ void sort (bool ignoreCase);
+
+ /** Sorts the array using extra language-aware rules to do a better job of comparing
+ words containing spaces and numbers.
+ @see String::compareNatural()
+ */
+ void sortNatural();
+
+ //==============================================================================
+ /** Increases the array's internal storage to hold a minimum number of elements.
+
+ Calling this before adding a large known number of elements means that
+ the array won't have to keep dynamically resizing itself as the elements
+ are added, and it'll therefore be more efficient.
+ */
+ void ensureStorageAllocated (int minNumElements);
+
+ /** Reduces the amount of storage being used by the array.
+
+ Arrays typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads();
+
+ /** This is the array holding the actual strings. This is public to allow direct access
+ to array methods that may not already be provided by the StringArray class.
+ */
+ Array<String> strings;
+
+private:
+ JUCE_LEAK_DETECTOR (StringArray)
+};
+
+
+#endif // JUCE_STRINGARRAY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.cpp
new file mode 100644
index 0000000..3275d2d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.cpp
@@ -0,0 +1,147 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+StringPairArray::StringPairArray (const bool ignoreCase_)
+ : ignoreCase (ignoreCase_)
+{
+}
+
+StringPairArray::StringPairArray (const StringPairArray& other)
+ : keys (other.keys),
+ values (other.values),
+ ignoreCase (other.ignoreCase)
+{
+}
+
+StringPairArray::~StringPairArray()
+{
+}
+
+StringPairArray& StringPairArray::operator= (const StringPairArray& other)
+{
+ keys = other.keys;
+ values = other.values;
+ return *this;
+}
+
+bool StringPairArray::operator== (const StringPairArray& other) const
+{
+ for (int i = keys.size(); --i >= 0;)
+ if (other [keys[i]] != values[i])
+ return false;
+
+ return true;
+}
+
+bool StringPairArray::operator!= (const StringPairArray& other) const
+{
+ return ! operator== (other);
+}
+
+const String& StringPairArray::operator[] (StringRef key) const
+{
+ return values [keys.indexOf (key, ignoreCase)];
+}
+
+String StringPairArray::getValue (StringRef key, const String& defaultReturnValue) const
+{
+ const int i = keys.indexOf (key, ignoreCase);
+
+ if (i >= 0)
+ return values[i];
+
+ return defaultReturnValue;
+}
+
+bool StringPairArray::containsKey (StringRef key) const noexcept
+{
+ return keys.contains (key);
+}
+
+void StringPairArray::set (const String& key, const String& value)
+{
+ const int i = keys.indexOf (key, ignoreCase);
+
+ if (i >= 0)
+ {
+ values.set (i, value);
+ }
+ else
+ {
+ keys.add (key);
+ values.add (value);
+ }
+}
+
+void StringPairArray::addArray (const StringPairArray& other)
+{
+ for (int i = 0; i < other.size(); ++i)
+ set (other.keys[i], other.values[i]);
+}
+
+void StringPairArray::clear()
+{
+ keys.clear();
+ values.clear();
+}
+
+void StringPairArray::remove (StringRef key)
+{
+ remove (keys.indexOf (key, ignoreCase));
+}
+
+void StringPairArray::remove (const int index)
+{
+ keys.remove (index);
+ values.remove (index);
+}
+
+void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase)
+{
+ ignoreCase = shouldIgnoreCase;
+}
+
+String StringPairArray::getDescription() const
+{
+ String s;
+
+ for (int i = 0; i < keys.size(); ++i)
+ {
+ s << keys[i] << " = " << values[i];
+ if (i < keys.size())
+ s << ", ";
+ }
+
+ return s;
+}
+
+void StringPairArray::minimiseStorageOverheads()
+{
+ keys.minimiseStorageOverheads();
+ values.minimiseStorageOverheads();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.h
new file mode 100644
index 0000000..e1c774d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPairArray.h
@@ -0,0 +1,157 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STRINGPAIRARRAY_H_INCLUDED
+#define JUCE_STRINGPAIRARRAY_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A container for holding a set of strings which are keyed by another string.
+
+ @see StringArray
+*/
+class JUCE_API StringPairArray
+{
+public:
+ //==============================================================================
+ /** Creates an empty array */
+ StringPairArray (bool ignoreCaseWhenComparingKeys = true);
+
+ /** Creates a copy of another array */
+ StringPairArray (const StringPairArray& other);
+
+ /** Destructor. */
+ ~StringPairArray();
+
+ /** Copies the contents of another string array into this one */
+ StringPairArray& operator= (const StringPairArray& other);
+
+ //==============================================================================
+ /** Compares two arrays.
+ Comparisons are case-sensitive.
+ @returns true only if the other array contains exactly the same strings with the same keys
+ */
+ bool operator== (const StringPairArray& other) const;
+
+ /** Compares two arrays.
+ Comparisons are case-sensitive.
+ @returns false if the other array contains exactly the same strings with the same keys
+ */
+ bool operator!= (const StringPairArray& other) const;
+
+ //==============================================================================
+ /** Finds the value corresponding to a key string.
+
+ If no such key is found, this will just return an empty string. To check whether
+ a given key actually exists (because it might actually be paired with an empty string), use
+ the getAllKeys() method to obtain a list.
+
+ Obviously the reference returned shouldn't be stored for later use, as the
+ string it refers to may disappear when the array changes.
+
+ @see getValue
+ */
+ const String& operator[] (StringRef key) const;
+
+ /** Finds the value corresponding to a key string.
+ If no such key is found, this will just return the value provided as a default.
+ @see operator[]
+ */
+ String getValue (StringRef, const String& defaultReturnValue) const;
+
+ /** Returns true if the given key exists. */
+ bool containsKey (StringRef key) const noexcept;
+
+ /** Returns a list of all keys in the array. */
+ const StringArray& getAllKeys() const noexcept { return keys; }
+
+ /** Returns a list of all values in the array. */
+ const StringArray& getAllValues() const noexcept { return values; }
+
+ /** Returns the number of strings in the array */
+ inline int size() const noexcept { return keys.size(); };
+
+
+ //==============================================================================
+ /** Adds or amends a key/value pair.
+ If a value already exists with this key, its value will be overwritten,
+ otherwise the key/value pair will be added to the array.
+ */
+ void set (const String& key, const String& value);
+
+ /** Adds the items from another array to this one.
+ This is equivalent to using set() to add each of the pairs from the other array.
+ */
+ void addArray (const StringPairArray& other);
+
+ //==============================================================================
+ /** Removes all elements from the array. */
+ void clear();
+
+ /** Removes a string from the array based on its key.
+ If the key isn't found, nothing will happen.
+ */
+ void remove (StringRef key);
+
+ /** Removes a string from the array based on its index.
+ If the index is out-of-range, no action will be taken.
+ */
+ void remove (int index);
+
+ //==============================================================================
+ /** Indicates whether to use a case-insensitive search when looking up a key string.
+ */
+ void setIgnoresCase (bool shouldIgnoreCase);
+
+ //==============================================================================
+ /** Returns a descriptive string containing the items.
+ This is handy for dumping the contents of an array.
+ */
+ String getDescription() const;
+
+ //==============================================================================
+ /** Reduces the amount of storage being used by the array.
+
+ Arrays typically allocate slightly more storage than they need, and after
+ removing elements, they may have quite a lot of unused space allocated.
+ This method will reduce the amount of allocated storage to a minimum.
+ */
+ void minimiseStorageOverheads();
+
+
+private:
+ //==============================================================================
+ StringArray keys, values;
+ bool ignoreCase;
+
+ JUCE_LEAK_DETECTOR (StringPairArray)
+};
+
+
+#endif // JUCE_STRINGPAIRARRAY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.cpp
new file mode 100644
index 0000000..039a30b
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.cpp
@@ -0,0 +1,166 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+static const int minNumberOfStringsForGarbageCollection = 300;
+static const uint32 garbageCollectionInterval = 30000;
+
+
+StringPool::StringPool() noexcept : lastGarbageCollectionTime (0) {}
+StringPool::~StringPool() {}
+
+struct StartEndString
+{
+ StartEndString (String::CharPointerType s, String::CharPointerType e) noexcept : start (s), end (e) {}
+ operator String() const { return String (start, end); }
+
+ String::CharPointerType start, end;
+};
+
+static int compareStrings (const String& s1, const String& s2) noexcept { return s1.compare (s2); }
+static int compareStrings (CharPointer_UTF8 s1, const String& s2) noexcept { return s1.compare (s2.getCharPointer()); }
+
+static int compareStrings (const StartEndString& string1, const String& string2) noexcept
+{
+ String::CharPointerType s1 (string1.start), s2 (string2.getCharPointer());
+
+ for (;;)
+ {
+ const int c1 = s1 < string1.end ? (int) s1.getAndAdvance() : 0;
+ const int c2 = (int) s2.getAndAdvance();
+ const int diff = c1 - c2;
+
+ if (diff != 0) return diff < 0 ? -1 : 1;
+ if (c1 == 0) break;
+ }
+
+ return 0;
+}
+
+template <typename NewStringType>
+static String addPooledString (Array<String>& strings, const NewStringType& newString)
+{
+ int start = 0;
+ int end = strings.size();
+
+ while (start < end)
+ {
+ const String& startString = strings.getReference (start);
+ const int startComp = compareStrings (newString, startString);
+
+ if (startComp == 0)
+ return startString;
+
+ const int halfway = (start + end) / 2;
+
+ if (halfway == start)
+ {
+ if (startComp > 0)
+ ++start;
+
+ break;
+ }
+
+ const String& halfwayString = strings.getReference (halfway);
+ const int halfwayComp = compareStrings (newString, halfwayString);
+
+ if (halfwayComp == 0)
+ return halfwayString;
+
+ if (halfwayComp > 0)
+ start = halfway;
+ else
+ end = halfway;
+ }
+
+ strings.insert (start, newString);
+ return strings.getReference (start);
+}
+
+String StringPool::getPooledString (const char* const newString)
+{
+ if (newString == nullptr || *newString == 0)
+ return String();
+
+ const ScopedLock sl (lock);
+ garbageCollectIfNeeded();
+ return addPooledString (strings, CharPointer_UTF8 (newString));
+}
+
+String StringPool::getPooledString (String::CharPointerType start, String::CharPointerType end)
+{
+ if (start.isEmpty() || start == end)
+ return String();
+
+ const ScopedLock sl (lock);
+ garbageCollectIfNeeded();
+ return addPooledString (strings, StartEndString (start, end));
+}
+
+String StringPool::getPooledString (StringRef newString)
+{
+ if (newString.isEmpty())
+ return String();
+
+ const ScopedLock sl (lock);
+ garbageCollectIfNeeded();
+ return addPooledString (strings, newString.text);
+}
+
+String StringPool::getPooledString (const String& newString)
+{
+ if (newString.isEmpty())
+ return String();
+
+ const ScopedLock sl (lock);
+ garbageCollectIfNeeded();
+ return addPooledString (strings, newString);
+}
+
+void StringPool::garbageCollectIfNeeded()
+{
+ if (strings.size() > minNumberOfStringsForGarbageCollection
+ && Time::getApproximateMillisecondCounter() > lastGarbageCollectionTime + garbageCollectionInterval)
+ garbageCollect();
+}
+
+void StringPool::garbageCollect()
+{
+ const ScopedLock sl (lock);
+
+ for (int i = strings.size(); --i >= 0;)
+ if (strings.getReference(i).getReferenceCount() == 1)
+ strings.remove (i);
+
+ lastGarbageCollectionTime = Time::getApproximateMillisecondCounter();
+}
+
+StringPool& StringPool::getGlobalPool() noexcept
+{
+ static StringPool pool;
+ return pool;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.h
new file mode 100644
index 0000000..4de2186
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringPool.h
@@ -0,0 +1,94 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STRINGPOOL_H_INCLUDED
+#define JUCE_STRINGPOOL_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A StringPool holds a set of shared strings, which reduces storage overheads and improves
+ comparison speed when dealing with many duplicate strings.
+
+ When you add a string to a pool using getPooledString, it'll return a character
+ array containing the same string. This array is owned by the pool, and the same array
+ is returned every time a matching string is asked for. This means that it's trivial to
+ compare two pooled strings for equality, as you can simply compare their pointers. It
+ also cuts down on storage if you're using many copies of the same string.
+*/
+class JUCE_API StringPool
+{
+public:
+ //==============================================================================
+ /** Creates an empty pool. */
+ StringPool() noexcept;
+
+ /** Destructor */
+ ~StringPool();
+
+ //==============================================================================
+ /** Returns a pointer to a shared copy of the string that is passed in.
+ The pool will always return the same String object when asked for a string that matches it.
+ */
+ String getPooledString (const String& original);
+
+ /** Returns a pointer to a copy of the string that is passed in.
+ The pool will always return the same String object when asked for a string that matches it.
+ */
+ String getPooledString (const char* original);
+
+ /** Returns a pointer to a shared copy of the string that is passed in.
+ The pool will always return the same String object when asked for a string that matches it.
+ */
+ String getPooledString (StringRef original);
+
+ /** Returns a pointer to a copy of the string that is passed in.
+ The pool will always return the same String object when asked for a string that matches it.
+ */
+ String getPooledString (String::CharPointerType start, String::CharPointerType end);
+
+ //==============================================================================
+ /** Scans the pool, and removes any strings that are unreferenced.
+ You don't generally need to call this - it'll be called automatically when the pool grows
+ large enough to warrant it.
+ */
+ void garbageCollect();
+
+ /** Returns a shared global pool which is used for things like Identifiers, XML parsing. */
+ static StringPool& getGlobalPool() noexcept;
+
+private:
+ Array<String> strings;
+ CriticalSection lock;
+ uint32 lastGarbageCollectionTime;
+
+ void garbageCollectIfNeeded();
+};
+
+
+#endif // JUCE_STRINGPOOL_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringRef.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringRef.h
new file mode 100644
index 0000000..434bf4a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_StringRef.h
@@ -0,0 +1,138 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_STRINGREF_H_INCLUDED
+#define JUCE_STRINGREF_H_INCLUDED
+
+//==============================================================================
+/**
+ A simple class for holding temporary references to a string literal or String.
+
+ Unlike a real String object, the StringRef does not allocate any memory or
+ take ownership of the strings you give to it - it simply holds a reference to
+ a string that has been allocated elsewhere.
+ The main purpose of the class is to be used instead of a const String& as the type
+ of function arguments where the caller may pass either a string literal or a String
+ object. This means that when the called uses a string literal, there's no need
+ for an temporary String object to be allocated, and this cuts down overheads
+ substantially.
+
+ Because the class is simply a wrapper around a pointer, you should always pass
+ it by value, not by reference.
+
+ @code
+ void myStringFunction1 (const String&);
+ void myStringFunction2 (StringRef);
+
+ myStringFunction1 ("abc"); // Implicitly allocates a temporary String object.
+ myStringFunction2 ("abc"); // Much faster, as no local allocations are needed.
+ @endcode
+
+ For examples of it in use, see the XmlElement or StringArray classes.
+
+ Bear in mind that there are still many cases where it's better to use an argument
+ which is a const String&. For example if the function stores the string or needs
+ to internally create a String from the argument, then it's better for the original
+ argument to already be a String.
+
+ @see String
+*/
+class JUCE_API StringRef
+{
+public:
+ /** Creates a StringRef from a raw string literal.
+ The StringRef object does NOT take ownership or copy this data, so you must
+ ensure that the data does not change during the lifetime of the StringRef.
+ Note that this pointer not be null!
+ */
+ StringRef (const char* stringLiteral) noexcept;
+
+ /** Creates a StringRef from a raw char pointer.
+ The StringRef object does NOT take ownership or copy this data, so you must
+ ensure that the data does not change during the lifetime of the StringRef.
+ */
+ StringRef (String::CharPointerType stringLiteral) noexcept;
+
+ /** Creates a StringRef from a String.
+ The StringRef object does NOT take ownership or copy the data from the String,
+ so you must ensure that the String is not modified or deleted during the lifetime
+ of the StringRef.
+ */
+ StringRef (const String& string) noexcept;
+
+ /** Creates a StringRef pointer to an empty string. */
+ StringRef() noexcept;
+
+ //==============================================================================
+ /** Returns a raw pointer to the underlying string data. */
+ operator const String::CharPointerType::CharType*() const noexcept { return text.getAddress(); }
+ /** Returns a pointer to the underlying string data as a char pointer object. */
+ operator String::CharPointerType() const noexcept { return text; }
+
+ /** Returns true if the string is empty. */
+ bool isEmpty() const noexcept { return text.isEmpty(); }
+ /** Returns true if the string is not empty. */
+ bool isNotEmpty() const noexcept { return ! text.isEmpty(); }
+ /** Returns the number of characters in the string. */
+ int length() const noexcept { return (int) text.length(); }
+
+ /** Retrieves a character by index. */
+ juce_wchar operator[] (int index) const noexcept { return text[index]; }
+
+ /** Compares this StringRef with a String. */
+ bool operator== (const String& s) const noexcept { return text.compare (s.getCharPointer()) == 0; }
+ /** Compares this StringRef with a String. */
+ bool operator!= (const String& s) const noexcept { return text.compare (s.getCharPointer()) != 0; }
+
+ /** Case-sensitive comparison of two StringRefs. */
+ bool operator== (StringRef s) const noexcept { return text.compare (s.text) == 0; }
+ /** Case-sensitive comparison of two StringRefs. */
+ bool operator!= (StringRef s) const noexcept { return text.compare (s.text) != 0; }
+
+ //==============================================================================
+ /** The text that is referenced. */
+ String::CharPointerType text;
+
+ #if JUCE_STRING_UTF_TYPE != 8 && ! defined (DOXYGEN)
+ // Sorry, non-UTF8 people, you're unable to take advantage of StringRef, because
+ // you've chosen a character encoding that doesn't match C++ string literals.
+ String stringCopy;
+ #endif
+};
+
+//==============================================================================
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator== (const String& string1, StringRef string2) noexcept;
+/** Case-sensitive comparison of two strings. */
+JUCE_API bool JUCE_CALLTYPE operator!= (const String& string1, StringRef string2) noexcept;
+
+#if JUCE_STRING_UTF_TYPE != 8 && ! defined (DOXYGEN)
+ inline String operator+ (String s1, StringRef s2) { return s1 += String (s2.text); }
+#endif
+
+#endif // JUCE_STRINGREF_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.cpp
new file mode 100644
index 0000000..6b4c807
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.cpp
@@ -0,0 +1,247 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+struct TextDiffHelpers
+{
+ enum { minLengthToMatch = 3 };
+
+ struct StringRegion
+ {
+ StringRegion (const String& s) noexcept
+ : text (s.getCharPointer()), start (0), length (s.length()) {}
+
+ StringRegion (const String::CharPointerType t, int s, int len) noexcept
+ : text (t), start (s), length (len) {}
+
+ String::CharPointerType text;
+ int start, length;
+ };
+
+ static void addInsertion (TextDiff& td, const String::CharPointerType text, int index, int length)
+ {
+ TextDiff::Change c;
+ c.insertedText = String (text, (size_t) length);
+ c.start = index;
+ c.length = length;
+ td.changes.add (c);
+ }
+
+ static void addDeletion (TextDiff& td, int index, int length)
+ {
+ TextDiff::Change c;
+ c.start = index;
+ c.length = length;
+ td.changes.add (c);
+ }
+
+ static void diffSkippingCommonStart (TextDiff& td, const StringRegion& a, const StringRegion& b)
+ {
+ String::CharPointerType sa (a.text);
+ String::CharPointerType sb (b.text);
+ const int maxLen = jmax (a.length, b.length);
+
+ for (int i = 0; i < maxLen; ++i, ++sa, ++sb)
+ {
+ if (*sa != *sb)
+ {
+ diffRecursively (td, StringRegion (sa, a.start + i, a.length - i),
+ StringRegion (sb, b.start + i, b.length - i));
+ break;
+ }
+ }
+ }
+
+ static void diffRecursively (TextDiff& td, const StringRegion& a, const StringRegion& b)
+ {
+ int indexA, indexB;
+ const int len = findLongestCommonSubstring (a.text, a.length,
+ b.text, b.length,
+ indexA, indexB);
+
+ if (len >= minLengthToMatch)
+ {
+ if (indexA > 0 && indexB > 0)
+ diffSkippingCommonStart (td, StringRegion (a.text, a.start, indexA),
+ StringRegion (b.text, b.start, indexB));
+ else if (indexA > 0)
+ addDeletion (td, b.start, indexA);
+ else if (indexB > 0)
+ addInsertion (td, b.text, b.start, indexB);
+
+ diffRecursively (td, StringRegion (a.text + indexA + len, a.start + indexA + len, a.length - indexA - len),
+ StringRegion (b.text + indexB + len, b.start + indexB + len, b.length - indexB - len));
+ }
+ else
+ {
+ if (a.length > 0) addDeletion (td, b.start, a.length);
+ if (b.length > 0) addInsertion (td, b.text, b.start, b.length);
+ }
+ }
+
+ static int findLongestCommonSubstring (String::CharPointerType a, const int lenA,
+ const String::CharPointerType b, const int lenB,
+ int& indexInA, int& indexInB)
+ {
+ if (lenA == 0 || lenB == 0)
+ return 0;
+
+ HeapBlock<int> lines;
+ lines.calloc (2 + 2 * (size_t) lenB);
+
+ int* l0 = lines;
+ int* l1 = l0 + lenB + 1;
+
+ int loopsWithoutImprovement = 0;
+ int bestLength = 0;
+ indexInA = indexInB = 0;
+
+ for (int i = 0; i < lenA; ++i)
+ {
+ const juce_wchar ca = a.getAndAdvance();
+ String::CharPointerType b2 (b);
+
+ for (int j = 0; j < lenB; ++j)
+ {
+ if (ca != b2.getAndAdvance())
+ {
+ l1[j + 1] = 0;
+ }
+ else
+ {
+ const int len = l0[j] + 1;
+ l1[j + 1] = len;
+
+ if (len > bestLength)
+ {
+ loopsWithoutImprovement = 0;
+ bestLength = len;
+ indexInA = i;
+ indexInB = j;
+ }
+ }
+ }
+
+ if (++loopsWithoutImprovement > 100)
+ break;
+
+ std::swap (l0, l1);
+ }
+
+ indexInA -= bestLength - 1;
+ indexInB -= bestLength - 1;
+ return bestLength;
+ }
+};
+
+TextDiff::TextDiff (const String& original, const String& target)
+{
+ TextDiffHelpers::diffSkippingCommonStart (*this, original, target);
+}
+
+String TextDiff::appliedTo (String text) const
+{
+ for (int i = 0; i < changes.size(); ++i)
+ text = changes.getReference(i).appliedTo (text);
+
+ return text;
+}
+
+bool TextDiff::Change::isDeletion() const noexcept
+{
+ return insertedText.isEmpty();
+}
+
+String TextDiff::Change::appliedTo (const String& text) const noexcept
+{
+ return text.substring (0, start) + (isDeletion() ? text.substring (start + length)
+ : (insertedText + text.substring (start)));
+}
+
+//==============================================================================
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class DiffTests : public UnitTest
+{
+public:
+ DiffTests() : UnitTest ("TextDiff class") {}
+
+ static String createString (Random& r)
+ {
+ juce_wchar buffer[50] = { 0 };
+
+ for (int i = r.nextInt (49); --i >= 0;)
+ {
+ if (r.nextInt (10) == 0)
+ {
+ do
+ {
+ buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
+ }
+ while (! CharPointer_UTF16::canRepresent (buffer[i]));
+ }
+ else
+ buffer[i] = (juce_wchar) ('a' + r.nextInt (3));
+ }
+
+ return CharPointer_UTF32 (buffer);
+ }
+
+ void testDiff (const String& a, const String& b)
+ {
+ TextDiff diff (a, b);
+ const String result (diff.appliedTo (a));
+ expectEquals (result, b);
+ }
+
+ void runTest()
+ {
+ beginTest ("TextDiff");
+
+ Random r = getRandom();
+
+ testDiff (String::empty, String::empty);
+ testDiff ("x", String::empty);
+ testDiff (String::empty, "x");
+ testDiff ("x", "x");
+ testDiff ("x", "y");
+ testDiff ("xxx", "x");
+ testDiff ("x", "xxx");
+
+ for (int i = 5000; --i >= 0;)
+ {
+ String s (createString (r));
+ testDiff (s, createString (r));
+ testDiff (s + createString (r), s + createString (r));
+ }
+ }
+};
+
+static DiffTests diffTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.h b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.h
new file mode 100644
index 0000000..d420c3d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/text/juce_TextDiff.h
@@ -0,0 +1,80 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_TEXTDIFF_H_INCLUDED
+#define JUCE_TEXTDIFF_H_INCLUDED
+
+
+/**
+ Calculates and applies a sequence of changes to convert one text string into
+ another.
+
+ Once created, the TextDiff object contains an array of change objects, where
+ each change can be either an insertion or a deletion. When applied in order
+ to the original string, these changes will convert it to the target string.
+*/
+class JUCE_API TextDiff
+{
+public:
+ /** Creates a set of diffs for converting the original string into the target. */
+ TextDiff (const String& original,
+ const String& target);
+
+ /** Applies this sequence of changes to the original string, producing the
+ target string that was specified when generating them.
+
+ Obviously it only makes sense to call this function with the string that
+ was originally passed to the constructor. Any other input will produce an
+ undefined result.
+ */
+ String appliedTo (String text) const;
+
+ /** Describes a change, which can be either an insertion or deletion. */
+ struct Change
+ {
+ String insertedText; /**< If this change is a deletion, this string will be empty; otherwise,
+ it'll be the text that should be inserted at the index specified by start. */
+ int start; /**< Specifies the character index in a string at which text should be inserted or deleted. */
+ int length; /**< If this change is a deletion, this specifies the number of characters to delete. For an
+ insertion, this is the length of the new text being inserted. */
+
+ /** Returns true if this change is a deletion, or false for an insertion. */
+ bool isDeletion() const noexcept;
+
+ /** Returns the result of applying this change to a string. */
+ String appliedTo (const String& original) const noexcept;
+ };
+
+ /** The list of changes required to perform the transformation.
+ Applying each of these, in order, to the original string will produce the target.
+ */
+ Array<Change> changes;
+};
+
+
+#endif // JUCE_TEXTDIFF_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.cpp
new file mode 100644
index 0000000..4566b13
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.cpp
@@ -0,0 +1,113 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+ChildProcess::ChildProcess() {}
+ChildProcess::~ChildProcess() {}
+
+bool ChildProcess::isRunning() const
+{
+ return activeProcess != nullptr && activeProcess->isRunning();
+}
+
+int ChildProcess::readProcessOutput (void* dest, int numBytes)
+{
+ return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0;
+}
+
+bool ChildProcess::kill()
+{
+ return activeProcess == nullptr || activeProcess->killProcess();
+}
+
+uint32 ChildProcess::getExitCode() const
+{
+ return activeProcess != nullptr ? activeProcess->getExitCode() : 0;
+}
+
+bool ChildProcess::waitForProcessToFinish (const int timeoutMs) const
+{
+ const uint32 timeoutTime = Time::getMillisecondCounter() + (uint32) timeoutMs;
+
+ do
+ {
+ if (! isRunning())
+ return true;
+ }
+ while (timeoutMs < 0 || Time::getMillisecondCounter() < timeoutTime);
+
+ return false;
+}
+
+String ChildProcess::readAllProcessOutput()
+{
+ MemoryOutputStream result;
+
+ for (;;)
+ {
+ char buffer [512];
+ const int num = readProcessOutput (buffer, sizeof (buffer));
+
+ if (num <= 0)
+ break;
+
+ result.write (buffer, (size_t) num);
+ }
+
+ return result.toString();
+}
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class ChildProcessTests : public UnitTest
+{
+public:
+ ChildProcessTests() : UnitTest ("ChildProcess") {}
+
+ void runTest()
+ {
+ beginTest ("Child Processes");
+
+ #if JUCE_WINDOWS || JUCE_MAC || JUCE_LINUX
+ ChildProcess p;
+
+ #if JUCE_WINDOWS
+ expect (p.start ("tasklist"));
+ #else
+ expect (p.start ("ls /"));
+ #endif
+
+ //String output (p.readAllProcessOutput());
+ //expect (output.isNotEmpty());
+ #endif
+ }
+};
+
+static ChildProcessTests childProcessUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.h
new file mode 100644
index 0000000..0adcb57
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ChildProcess.h
@@ -0,0 +1,119 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CHILDPROCESS_H_INCLUDED
+#define JUCE_CHILDPROCESS_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Launches and monitors a child process.
+
+ This class lets you launch an executable, and read its output. You can also
+ use it to check whether the child process has finished.
+*/
+class JUCE_API ChildProcess
+{
+public:
+ //==============================================================================
+ /** Creates a process object.
+ To actually launch the process, use start().
+ */
+ ChildProcess();
+
+ /** Destructor.
+ Note that deleting this object won't terminate the child process.
+ */
+ ~ChildProcess();
+
+ /** These flags are used by the start() methods. */
+ enum StreamFlags
+ {
+ wantStdOut = 1,
+ wantStdErr = 2
+ };
+
+ /** Attempts to launch a child process command.
+
+ The command should be the name of the executable file, followed by any arguments
+ that are required.
+ If the process has already been launched, this will launch it again. If a problem
+ occurs, the method will return false.
+ The streamFlags is a combinations of values to indicate which of the child's output
+ streams should be read and returned by readProcessOutput().
+ */
+ bool start (const String& command, int streamFlags = wantStdOut | wantStdErr);
+
+ /** Attempts to launch a child process command.
+
+ The first argument should be the name of the executable file, followed by any other
+ arguments that are needed.
+ If the process has already been launched, this will launch it again. If a problem
+ occurs, the method will return false.
+ The streamFlags is a combinations of values to indicate which of the child's output
+ streams should be read and returned by readProcessOutput().
+ */
+ bool start (const StringArray& arguments, int streamFlags = wantStdOut | wantStdErr);
+
+ /** Returns true if the child process is alive. */
+ bool isRunning() const;
+
+ /** Attempts to read some output from the child process.
+ This will attempt to read up to the given number of bytes of data from the
+ process. It returns the number of bytes that were actually read.
+ */
+ int readProcessOutput (void* destBuffer, int numBytesToRead);
+
+ /** Blocks until the process has finished, and then returns its complete output
+ as a string.
+ */
+ String readAllProcessOutput();
+
+ /** Blocks until the process is no longer running. */
+ bool waitForProcessToFinish (int timeoutMs) const;
+
+ /** If the process has finished, this returns its exit code. */
+ uint32 getExitCode() const;
+
+ /** Attempts to kill the child process.
+ Returns true if it succeeded. Trying to read from the process after calling this may
+ result in undefined behaviour.
+ */
+ bool kill();
+
+private:
+ //==============================================================================
+ class ActiveProcess;
+ friend struct ContainerDeletePolicy<ActiveProcess>;
+ ScopedPointer<ActiveProcess> activeProcess;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcess)
+};
+
+
+#endif // JUCE_CHILDPROCESS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_CriticalSection.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_CriticalSection.h
new file mode 100644
index 0000000..60e61dd
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_CriticalSection.h
@@ -0,0 +1,266 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_CRITICALSECTION_H_INCLUDED
+#define JUCE_CRITICALSECTION_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A re-entrant mutex.
+
+ A CriticalSection acts as a re-entrant mutex object. The best way to lock and unlock
+ one of these is by using RAII in the form of a local ScopedLock object - have a look
+ through the codebase for many examples of how to do this.
+
+ In almost all cases you'll want to declare your CriticalSection as a member variable.
+ Occasionally you may want to declare one as a static variable, but in that case the usual
+ C++ static object order-of-construction warnings should be heeded.
+
+ @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock
+*/
+class JUCE_API CriticalSection
+{
+public:
+ //==============================================================================
+ /** Creates a CriticalSection object. */
+ CriticalSection() noexcept;
+
+ /** Destructor.
+ If the critical section is deleted whilst locked, any subsequent behaviour
+ is unpredictable.
+ */
+ ~CriticalSection() noexcept;
+
+ //==============================================================================
+ /** Acquires the lock.
+
+ If the lock is already held by the caller thread, the method returns immediately.
+ If the lock is currently held by another thread, this will wait until it becomes free.
+
+ It's strongly recommended that you never call this method directly - instead use the
+ ScopedLock class to manage the locking using an RAII pattern instead.
+
+ @see exit, tryEnter, ScopedLock
+ */
+ void enter() const noexcept;
+
+ /** Attempts to lock this critical section without blocking.
+
+ This method behaves identically to CriticalSection::enter, except that the caller thread
+ does not wait if the lock is currently held by another thread but returns false immediately.
+
+ @returns false if the lock is currently held by another thread, true otherwise.
+ @see enter
+ */
+ bool tryEnter() const noexcept;
+
+ /** Releases the lock.
+
+ If the caller thread hasn't got the lock, this can have unpredictable results.
+
+ If the enter() method has been called multiple times by the thread, each
+ call must be matched by a call to exit() before other threads will be allowed
+ to take over the lock.
+
+ @see enter, ScopedLock
+ */
+ void exit() const noexcept;
+
+
+ //==============================================================================
+ /** Provides the type of scoped lock to use with a CriticalSection. */
+ typedef GenericScopedLock <CriticalSection> ScopedLockType;
+
+ /** Provides the type of scoped unlocker to use with a CriticalSection. */
+ typedef GenericScopedUnlock <CriticalSection> ScopedUnlockType;
+
+ /** Provides the type of scoped try-locker to use with a CriticalSection. */
+ typedef GenericScopedTryLock <CriticalSection> ScopedTryLockType;
+
+
+private:
+ //==============================================================================
+ #if JUCE_WINDOWS
+ // To avoid including windows.h in the public JUCE headers, we'll just allocate
+ // a block of memory here that's big enough to be used internally as a windows
+ // CRITICAL_SECTION structure.
+ #if JUCE_64BIT
+ uint8 lock[44];
+ #else
+ uint8 lock[24];
+ #endif
+ #else
+ mutable pthread_mutex_t lock;
+ #endif
+
+ JUCE_DECLARE_NON_COPYABLE (CriticalSection)
+};
+
+
+//==============================================================================
+/**
+ A class that can be used in place of a real CriticalSection object, but which
+ doesn't perform any locking.
+
+ This is currently used by some templated classes, and most compilers should
+ manage to optimise it out of existence.
+
+ @see CriticalSection, Array, OwnedArray, ReferenceCountedArray
+*/
+class JUCE_API DummyCriticalSection
+{
+public:
+ inline DummyCriticalSection() noexcept {}
+ inline ~DummyCriticalSection() noexcept {}
+
+ inline void enter() const noexcept {}
+ inline bool tryEnter() const noexcept { return true; }
+ inline void exit() const noexcept {}
+
+ //==============================================================================
+ /** A dummy scoped-lock type to use with a dummy critical section. */
+ struct ScopedLockType
+ {
+ ScopedLockType (const DummyCriticalSection&) noexcept {}
+ };
+
+ /** A dummy scoped-unlocker type to use with a dummy critical section. */
+ typedef ScopedLockType ScopedUnlockType;
+
+private:
+ JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection)
+};
+
+//==============================================================================
+/**
+ Automatically locks and unlocks a CriticalSection object.
+
+ You can use a ScopedLock as a local variable to provide RAII-based locking of a CriticalSection.
+
+ e.g. @code
+
+ struct MyObject
+ {
+ CriticalSection objectLock;
+
+ // assuming that this example function will be called by multiple threads
+ void foo()
+ {
+ const ScopedLock myScopedLock (objectLock);
+
+ // objectLock is now locked..
+
+ ...do some thread-safe work here...
+
+ // ..and objectLock gets unlocked here, as myScopedLock goes out of
+ // scope at the end of the block
+ }
+ };
+ @endcode
+
+ @see CriticalSection, ScopedUnlock
+*/
+typedef CriticalSection::ScopedLockType ScopedLock;
+
+//==============================================================================
+/**
+ Automatically unlocks and re-locks a CriticalSection object.
+
+ This is the reverse of a ScopedLock object - instead of locking the critical
+ section for the lifetime of this object, it unlocks it.
+
+ Make sure you don't try to unlock critical sections that aren't actually locked!
+
+ e.g. @code
+
+ struct MyObject
+ {
+ CriticalSection objectLock;
+
+ void foo()
+ {
+ {
+ const ScopedLock myScopedLock (objectLock);
+
+ // objectLock is now locked..
+
+ {
+ ScopedUnlock myUnlocker (objectLock);
+
+ // ..and now unlocked..
+ }
+
+ // ..and now locked again..
+ }
+
+ // ..and finally unlocked.
+ }
+ };
+ @endcode
+
+ @see CriticalSection, ScopedLock
+*/
+typedef CriticalSection::ScopedUnlockType ScopedUnlock;
+
+//==============================================================================
+/**
+ Automatically tries to lock and unlock a CriticalSection object.
+
+ Use one of these as a local variable to control access to a CriticalSection.
+
+ e.g. @code
+
+ struct MyObject
+ {
+ CriticalSection objectLock;
+
+ void foo()
+ {
+ const ScopedTryLock myScopedTryLock (objectLock);
+
+ // Unlike using a ScopedLock, this may fail to actually get the lock, so you
+ // must call the isLocked() method before making any assumptions..
+ if (myScopedTryLock.isLocked())
+ {
+ ...safely do some work...
+ }
+ else
+ {
+ // If we get here, then our attempt at locking failed because another thread had already locked it..
+ }
+ }
+ };
+ @endcode
+
+ @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock
+*/
+typedef CriticalSection::ScopedTryLockType ScopedTryLock;
+
+
+#endif // JUCE_CRITICALSECTION_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_DynamicLibrary.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_DynamicLibrary.h
new file mode 100644
index 0000000..df6625b
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_DynamicLibrary.h
@@ -0,0 +1,85 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_DYNAMICLIBRARY_H_INCLUDED
+#define JUCE_DYNAMICLIBRARY_H_INCLUDED
+
+/**
+ Handles the opening and closing of DLLs.
+
+ This class can be used to open a DLL and get some function pointers from it.
+ Since the DLL is freed when this object is deleted, it's handy for managing
+ library lifetimes using RAII.
+*/
+class JUCE_API DynamicLibrary
+{
+public:
+ /** Creates an unopened DynamicLibrary object.
+ Call open() to actually open one.
+ */
+ DynamicLibrary() noexcept : handle (nullptr) {}
+
+ /**
+ */
+ DynamicLibrary (const String& name) : handle (nullptr) { open (name); }
+
+ /** Destructor.
+ If a library is currently open, it will be closed when this object is destroyed.
+ */
+ ~DynamicLibrary() { close(); }
+
+ /** Opens a DLL.
+ The name and the method by which it gets found is of course platform-specific, and
+ may or may not include a path, depending on the OS.
+ If a library is already open when this method is called, it will first close the library
+ before attempting to load the new one.
+ @returns true if the library was successfully found and opened.
+ */
+ bool open (const String& name);
+
+ /** Releases the currently-open DLL, or has no effect if none was open. */
+ void close();
+
+ /** Tries to find a named function in the currently-open DLL, and returns a pointer to it.
+ If no library is open, or if the function isn't found, this will return a null pointer.
+ */
+ void* getFunction (const String& functionName) noexcept;
+
+ /** Returns the platform-specific native library handle.
+ You'll need to cast this to whatever is appropriate for the OS that's in use.
+ */
+ void* getNativeHandle() const noexcept { return handle; }
+
+private:
+ void* handle;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DynamicLibrary)
+};
+
+
+#endif // JUCE_DYNAMICLIBRARY_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.cpp
new file mode 100644
index 0000000..3475b74
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.cpp
@@ -0,0 +1,36 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+HighResolutionTimer::HighResolutionTimer() { pimpl = new Pimpl (*this); }
+HighResolutionTimer::~HighResolutionTimer() { stopTimer(); }
+
+void HighResolutionTimer::startTimer (int periodMs) { pimpl->start (jmax (1, periodMs)); }
+void HighResolutionTimer::stopTimer() { pimpl->stop(); }
+
+bool HighResolutionTimer::isTimerRunning() const noexcept { return pimpl->periodMs != 0; }
+int HighResolutionTimer::getTimerInterval() const noexcept { return pimpl->periodMs; }
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.h
new file mode 100644
index 0000000..21022ad
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_HighResolutionTimer.h
@@ -0,0 +1,109 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_HIGHRESOLUTIONTIMER_H_INCLUDED
+#define JUCE_HIGHRESOLUTIONTIMER_H_INCLUDED
+
+/**
+ A high-resolution periodic timer.
+
+ This provides accurately-timed regular callbacks. Unlike the normal Timer
+ class, this one uses a dedicated thread, not the message thread, so is
+ far more stable and precise.
+
+ You should only use this class in situations where you really need accuracy,
+ because unlike the normal Timer class, which is very lightweight and cheap
+ to start/stop, the HighResolutionTimer will use far more resources, and
+ starting/stopping it may involve launching and killing threads.
+
+ @see Timer
+*/
+class JUCE_API HighResolutionTimer
+{
+protected:
+ /** Creates a HighResolutionTimer.
+ When created, the timer is stopped, so use startTimer() to get it going.
+ */
+ HighResolutionTimer();
+
+public:
+ /** Destructor. */
+ virtual ~HighResolutionTimer();
+
+ //==============================================================================
+ /** The user-defined callback routine that actually gets called periodically.
+
+ This will be called on a dedicated timer thread, so make sure your
+ implementation is thread-safe!
+
+ It's perfectly ok to call startTimer() or stopTimer() from within this
+ callback to change the subsequent intervals.
+ */
+ virtual void hiResTimerCallback() = 0;
+
+ //==============================================================================
+ /** Starts the timer and sets the length of interval required.
+
+ If the timer is already started, this will reset its counter, so the
+ time between calling this method and the next timer callback will not be
+ less than the interval length passed in.
+
+ @param intervalInMilliseconds the interval to use (any values less than 1 will be
+ rounded up to 1)
+ */
+ void startTimer (int intervalInMilliseconds);
+
+ /** Stops the timer.
+
+ This method may block while it waits for pending callbacks to complete. Once it
+ returns, no more callbacks will be made. If it is called from the timer's own thread,
+ it will cancel the timer after the current callback returns.
+ */
+ void stopTimer();
+
+ /** Checks if the timer has been started.
+ @returns true if the timer is running.
+ */
+ bool isTimerRunning() const noexcept;
+
+ /** Returns the timer's interval.
+ @returns the timer's interval in milliseconds if it's running, or 0 if it's not.
+ */
+ int getTimerInterval() const noexcept;
+
+private:
+ struct Pimpl;
+ friend struct Pimpl;
+ friend struct ContainerDeletePolicy<Pimpl>;
+ ScopedPointer<Pimpl> pimpl;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HighResolutionTimer)
+};
+
+
+#endif // JUCE_HIGHRESOLUTIONTIMER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_InterProcessLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_InterProcessLock.h
new file mode 100644
index 0000000..dc903b0
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_InterProcessLock.h
@@ -0,0 +1,128 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_INTERPROCESSLOCK_H_INCLUDED
+#define JUCE_INTERPROCESSLOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Acts as a critical section which processes can use to block each other.
+
+ @see CriticalSection
+*/
+class JUCE_API InterProcessLock
+{
+public:
+ //==============================================================================
+ /** Creates a lock object.
+ @param name a name that processes will use to identify this lock object
+ */
+ explicit InterProcessLock (const String& name);
+
+ /** Destructor.
+ This will also release the lock if it's currently held by this process.
+ */
+ ~InterProcessLock();
+
+ //==============================================================================
+ /** Attempts to lock the critical section.
+
+ @param timeOutMillisecs how many milliseconds to wait if the lock is already
+ held by another process - a value of 0 will return
+ immediately, negative values will wait forever
+ @returns true if the lock could be gained within the timeout period, or
+ false if the timeout expired.
+ */
+ bool enter (int timeOutMillisecs = -1);
+
+ /** Releases the lock if it's currently held by this process. */
+ void exit();
+
+ //==============================================================================
+ /**
+ Automatically locks and unlocks an InterProcessLock object.
+
+ This works like a ScopedLock, but using an InterprocessLock rather than
+ a CriticalSection.
+
+ @see ScopedLock
+ */
+ class ScopedLockType
+ {
+ public:
+ //==============================================================================
+ /** Creates a scoped lock.
+
+ As soon as it is created, this will lock the InterProcessLock, and
+ when the ScopedLockType object is deleted, the InterProcessLock will
+ be unlocked.
+
+ Note that since an InterprocessLock can fail due to errors, you should check
+ isLocked() to make sure that the lock was successful before using it.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ explicit ScopedLockType (InterProcessLock& l) : ipLock (l) { lockWasSuccessful = l.enter(); }
+
+ /** Destructor.
+
+ The InterProcessLock will be unlocked when the destructor is called.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen!
+ */
+ inline ~ScopedLockType() { ipLock.exit(); }
+
+ /** Returns true if the InterProcessLock was successfully locked. */
+ bool isLocked() const noexcept { return lockWasSuccessful; }
+
+ private:
+ //==============================================================================
+ InterProcessLock& ipLock;
+ bool lockWasSuccessful;
+
+ JUCE_DECLARE_NON_COPYABLE (ScopedLockType)
+ };
+
+private:
+ //==============================================================================
+ class Pimpl;
+ friend struct ContainerDeletePolicy<Pimpl>;
+ ScopedPointer<Pimpl> pimpl;
+
+ CriticalSection lock;
+ String name;
+
+ JUCE_DECLARE_NON_COPYABLE (InterProcessLock)
+};
+
+
+#endif // JUCE_INTERPROCESSLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Process.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Process.h
new file mode 100644
index 0000000..f3efd66
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Process.h
@@ -0,0 +1,153 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_PROCESS_H_INCLUDED
+#define JUCE_PROCESS_H_INCLUDED
+
+
+//==============================================================================
+/** Represents the current executable's process.
+
+ This contains methods for controlling the current application at the
+ process-level.
+
+ @see Thread, JUCEApplicationBase
+*/
+class JUCE_API Process
+{
+public:
+ //==============================================================================
+ enum ProcessPriority
+ {
+ LowPriority = 0,
+ NormalPriority = 1,
+ HighPriority = 2,
+ RealtimePriority = 3
+ };
+
+ /** Changes the current process's priority.
+
+ @param priority the process priority, where
+ 0=low, 1=normal, 2=high, 3=realtime
+ */
+ static void JUCE_CALLTYPE setPriority (const ProcessPriority priority);
+
+ /** Kills the current process immediately.
+
+ This is an emergency process terminator that kills the application
+ immediately - it's intended only for use only when something goes
+ horribly wrong.
+
+ @see JUCEApplicationBase::quit
+ */
+ static void JUCE_CALLTYPE terminate();
+
+ //==============================================================================
+ /** Returns true if this application process is the one that the user is
+ currently using.
+ */
+ static bool JUCE_CALLTYPE isForegroundProcess();
+
+ /** Attempts to make the current process the active one.
+ (This is not possible on some platforms).
+ */
+ static void JUCE_CALLTYPE makeForegroundProcess();
+
+ /** Hides the application (on an OS that supports this, e.g. OSX) */
+ static void JUCE_CALLTYPE hide();
+
+ //==============================================================================
+ /** Raises the current process's privilege level.
+
+ Does nothing if this isn't supported by the current OS, or if process
+ privilege level is fixed.
+ */
+ static void JUCE_CALLTYPE raisePrivilege();
+
+ /** Lowers the current process's privilege level.
+
+ Does nothing if this isn't supported by the current OS, or if process
+ privilege level is fixed.
+ */
+ static void JUCE_CALLTYPE lowerPrivilege();
+
+ //==============================================================================
+ /** Returns true if this process is being hosted by a debugger. */
+ static bool JUCE_CALLTYPE isRunningUnderDebugger();
+
+
+ //==============================================================================
+ /** Tries to launch the OS's default reader application for a given file or URL. */
+ static bool JUCE_CALLTYPE openDocument (const String& documentURL, const String& parameters);
+
+ /** Tries to launch the OS's default email application to let the user create a message. */
+ static bool JUCE_CALLTYPE openEmailWithAttachments (const String& targetEmailAddress,
+ const String& emailSubject,
+ const String& bodyText,
+ const StringArray& filesToAttach);
+
+ #if JUCE_WINDOWS || DOXYGEN
+ //==============================================================================
+ /** WINDOWS ONLY - This returns the HINSTANCE of the current module.
+
+ The return type is a void* to avoid being dependent on windows.h - just cast
+ it to a HINSTANCE to use it.
+
+ In a normal JUCE application, this will be automatically set to the module
+ handle of the executable.
+
+ If you've built a DLL and plan to use any JUCE messaging or windowing classes,
+ you'll need to make sure you call the setCurrentModuleInstanceHandle()
+ to provide the correct module handle in your DllMain() function, because
+ the system relies on the correct instance handle when opening windows.
+ */
+ static void* JUCE_CALLTYPE getCurrentModuleInstanceHandle() noexcept;
+
+ /** WINDOWS ONLY - Sets a new module handle to be used by the library.
+
+ The parameter type is a void* to avoid being dependent on windows.h, but it actually
+ expects a HINSTANCE value.
+
+ @see getCurrentModuleInstanceHandle()
+ */
+ static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) noexcept;
+ #endif
+
+ #if JUCE_MAC || DOXYGEN
+ //==============================================================================
+ /** OSX ONLY - Shows or hides the OSX dock icon for this app. */
+ static void setDockIconVisible (bool isVisible);
+ #endif
+
+private:
+ Process();
+ JUCE_DECLARE_NON_COPYABLE (Process)
+};
+
+
+#endif // JUCE_PROCESS_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.cpp
new file mode 100644
index 0000000..a0821b4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.cpp
@@ -0,0 +1,150 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+ReadWriteLock::ReadWriteLock() noexcept
+ : numWaitingWriters (0),
+ numWriters (0),
+ writerThreadId (0)
+{
+ readerThreads.ensureStorageAllocated (16);
+}
+
+ReadWriteLock::~ReadWriteLock() noexcept
+{
+ jassert (readerThreads.size() == 0);
+ jassert (numWriters == 0);
+}
+
+//==============================================================================
+void ReadWriteLock::enterRead() const noexcept
+{
+ while (! tryEnterRead())
+ waitEvent.wait (100);
+}
+
+bool ReadWriteLock::tryEnterRead() const noexcept
+{
+ const Thread::ThreadID threadId = Thread::getCurrentThreadId();
+
+ const SpinLock::ScopedLockType sl (accessLock);
+
+ for (int i = 0; i < readerThreads.size(); ++i)
+ {
+ ThreadRecursionCount& trc = readerThreads.getReference(i);
+
+ if (trc.threadID == threadId)
+ {
+ trc.count++;
+ return true;
+ }
+ }
+
+ if (numWriters + numWaitingWriters == 0
+ || (threadId == writerThreadId && numWriters > 0))
+ {
+ ThreadRecursionCount trc = { threadId, 1 };
+ readerThreads.add (trc);
+ return true;
+ }
+
+ return false;
+}
+
+void ReadWriteLock::exitRead() const noexcept
+{
+ const Thread::ThreadID threadId = Thread::getCurrentThreadId();
+ const SpinLock::ScopedLockType sl (accessLock);
+
+ for (int i = 0; i < readerThreads.size(); ++i)
+ {
+ ThreadRecursionCount& trc = readerThreads.getReference(i);
+
+ if (trc.threadID == threadId)
+ {
+ if (--(trc.count) == 0)
+ {
+ readerThreads.remove (i);
+ waitEvent.signal();
+ }
+
+ return;
+ }
+ }
+
+ jassertfalse; // unlocking a lock that wasn't locked..
+}
+
+//==============================================================================
+void ReadWriteLock::enterWrite() const noexcept
+{
+ const Thread::ThreadID threadId = Thread::getCurrentThreadId();
+ const SpinLock::ScopedLockType sl (accessLock);
+
+ while (! tryEnterWriteInternal (threadId))
+ {
+ ++numWaitingWriters;
+ accessLock.exit();
+ waitEvent.wait (100);
+ accessLock.enter();
+ --numWaitingWriters;
+ }
+}
+
+bool ReadWriteLock::tryEnterWrite() const noexcept
+{
+ const SpinLock::ScopedLockType sl (accessLock);
+ return tryEnterWriteInternal (Thread::getCurrentThreadId());
+}
+
+bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noexcept
+{
+ if (readerThreads.size() + numWriters == 0
+ || threadId == writerThreadId
+ || (readerThreads.size() == 1 && readerThreads.getReference(0).threadID == threadId))
+ {
+ writerThreadId = threadId;
+ ++numWriters;
+ return true;
+ }
+
+ return false;
+}
+
+void ReadWriteLock::exitWrite() const noexcept
+{
+ const SpinLock::ScopedLockType sl (accessLock);
+
+ // check this thread actually had the lock..
+ jassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId());
+
+ if (--numWriters == 0)
+ {
+ writerThreadId = 0;
+ waitEvent.signal();
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.h
new file mode 100644
index 0000000..c41d258
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ReadWriteLock.h
@@ -0,0 +1,152 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_READWRITELOCK_H_INCLUDED
+#define JUCE_READWRITELOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A critical section that allows multiple simultaneous readers.
+
+ Features of this type of lock are:
+
+ - Multiple readers can hold the lock at the same time, but only one writer
+ can hold it at once.
+ - Writers trying to gain the lock will be blocked until all readers and writers
+ have released it
+ - Readers trying to gain the lock while a writer is waiting to acquire it will be
+ blocked until the writer has obtained and released it
+ - If a thread already has a read lock and tries to obtain a write lock, it will succeed if
+ there are no other readers
+ - If a thread already has the write lock and tries to obtain a read lock, this will succeed.
+ - Recursive locking is supported.
+
+ @see ScopedReadLock, ScopedWriteLock, CriticalSection
+*/
+class JUCE_API ReadWriteLock
+{
+public:
+ //==============================================================================
+ /**
+ Creates a ReadWriteLock object.
+ */
+ ReadWriteLock() noexcept;
+
+ /** Destructor.
+ If the object is deleted whilst locked, any subsequent behaviour is undefined.
+ */
+ ~ReadWriteLock() noexcept;
+
+ //==============================================================================
+ /** Locks this object for reading.
+
+ Multiple threads can simultaneously lock the object for reading, but if another
+ thread has it locked for writing, then this will block until it releases the lock.
+
+ @see exitRead, ScopedReadLock
+ */
+ void enterRead() const noexcept;
+
+ /** Tries to lock this object for reading.
+
+ Multiple threads can simultaneously lock the object for reading, but if another
+ thread has it locked for writing, then this will fail and return false.
+
+ @returns true if the lock is successfully gained.
+ @see exitRead, ScopedReadLock
+ */
+ bool tryEnterRead() const noexcept;
+
+ /** Releases the read-lock.
+
+ If the caller thread hasn't got the lock, this can have unpredictable results.
+
+ If the enterRead() method has been called multiple times by the thread, each
+ call must be matched by a call to exitRead() before other threads will be allowed
+ to take over the lock.
+
+ @see enterRead, ScopedReadLock
+ */
+ void exitRead() const noexcept;
+
+ //==============================================================================
+ /** Locks this object for writing.
+
+ This will block until any other threads that have it locked for reading or
+ writing have released their lock.
+
+ @see exitWrite, ScopedWriteLock
+ */
+ void enterWrite() const noexcept;
+
+ /** Tries to lock this object for writing.
+
+ This is like enterWrite(), but doesn't block - it returns true if it manages
+ to obtain the lock.
+
+ @returns true if the lock is successfully gained.
+ @see enterWrite
+ */
+ bool tryEnterWrite() const noexcept;
+
+ /** Releases the write-lock.
+
+ If the caller thread hasn't got the lock, this can have unpredictable results.
+
+ If the enterWrite() method has been called multiple times by the thread, each
+ call must be matched by a call to exit() before other threads will be allowed
+ to take over the lock.
+
+ @see enterWrite, ScopedWriteLock
+ */
+ void exitWrite() const noexcept;
+
+
+private:
+ //==============================================================================
+ SpinLock accessLock;
+ WaitableEvent waitEvent;
+ mutable int numWaitingWriters, numWriters;
+ mutable Thread::ThreadID writerThreadId;
+
+ struct ThreadRecursionCount
+ {
+ Thread::ThreadID threadID;
+ int count;
+ };
+
+ mutable Array <ThreadRecursionCount> readerThreads;
+
+ bool tryEnterWriteInternal (Thread::ThreadID) const noexcept;
+
+ JUCE_DECLARE_NON_COPYABLE (ReadWriteLock)
+};
+
+
+#endif // JUCE_READWRITELOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedLock.h
new file mode 100644
index 0000000..442551a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedLock.h
@@ -0,0 +1,237 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SCOPEDLOCK_H_INCLUDED
+#define JUCE_SCOPEDLOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Automatically locks and unlocks a mutex object.
+
+ Use one of these as a local variable to provide RAII-based locking of a mutex.
+
+ The templated class could be a CriticalSection, SpinLock, or anything else that
+ provides enter() and exit() methods.
+
+ e.g. @code
+ CriticalSection myCriticalSection;
+
+ for (;;)
+ {
+ const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection);
+ // myCriticalSection is now locked
+
+ ...do some stuff...
+
+ // myCriticalSection gets unlocked here.
+ }
+ @endcode
+
+ @see GenericScopedUnlock, CriticalSection, SpinLock, ScopedLock, ScopedUnlock
+*/
+template <class LockType>
+class GenericScopedLock
+{
+public:
+ //==============================================================================
+ /** Creates a GenericScopedLock.
+
+ As soon as it is created, this will acquire the lock, and when the GenericScopedLock
+ object is deleted, the lock will be released.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ inline explicit GenericScopedLock (const LockType& lock) noexcept : lock_ (lock) { lock.enter(); }
+
+ /** Destructor.
+ The lock will be released when the destructor is called.
+ Make sure this object is created and deleted by the same thread, otherwise there are
+ no guarantees what will happen!
+ */
+ inline ~GenericScopedLock() noexcept { lock_.exit(); }
+
+private:
+ //==============================================================================
+ const LockType& lock_;
+
+ JUCE_DECLARE_NON_COPYABLE (GenericScopedLock)
+};
+
+
+//==============================================================================
+/**
+ Automatically unlocks and re-locks a mutex object.
+
+ This is the reverse of a GenericScopedLock object - instead of locking the mutex
+ for the lifetime of this object, it unlocks it.
+
+ Make sure you don't try to unlock mutexes that aren't actually locked!
+
+ e.g. @code
+
+ CriticalSection myCriticalSection;
+
+ for (;;)
+ {
+ const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection);
+ // myCriticalSection is now locked
+
+ ... do some stuff with it locked ..
+
+ while (xyz)
+ {
+ ... do some stuff with it locked ..
+
+ const GenericScopedUnlock<CriticalSection> unlocker (myCriticalSection);
+
+ // myCriticalSection is now unlocked for the remainder of this block,
+ // and re-locked at the end.
+
+ ...do some stuff with it unlocked ...
+ }
+
+ // myCriticalSection gets unlocked here.
+ }
+ @endcode
+
+ @see GenericScopedLock, CriticalSection, ScopedLock, ScopedUnlock
+*/
+template <class LockType>
+class GenericScopedUnlock
+{
+public:
+ //==============================================================================
+ /** Creates a GenericScopedUnlock.
+
+ As soon as it is created, this will unlock the CriticalSection, and
+ when the ScopedLock object is deleted, the CriticalSection will
+ be re-locked.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ inline explicit GenericScopedUnlock (const LockType& lock) noexcept : lock_ (lock) { lock.exit(); }
+
+ /** Destructor.
+
+ The CriticalSection will be unlocked when the destructor is called.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen!
+ */
+ inline ~GenericScopedUnlock() noexcept { lock_.enter(); }
+
+
+private:
+ //==============================================================================
+ const LockType& lock_;
+
+ JUCE_DECLARE_NON_COPYABLE (GenericScopedUnlock)
+};
+
+
+//==============================================================================
+/**
+ Automatically locks and unlocks a mutex object.
+
+ Use one of these as a local variable to provide RAII-based locking of a mutex.
+
+ The templated class could be a CriticalSection, SpinLock, or anything else that
+ provides enter() and exit() methods.
+
+ e.g. @code
+
+ CriticalSection myCriticalSection;
+
+ for (;;)
+ {
+ const GenericScopedTryLock<CriticalSection> myScopedTryLock (myCriticalSection);
+
+ // Unlike using a ScopedLock, this may fail to actually get the lock, so you
+ // should test this with the isLocked() method before doing your thread-unsafe
+ // action..
+ if (myScopedTryLock.isLocked())
+ {
+ ...do some stuff...
+ }
+ else
+ {
+ ..our attempt at locking failed because another thread had already locked it..
+ }
+
+ // myCriticalSection gets unlocked here (if it was locked)
+ }
+ @endcode
+
+ @see CriticalSection::tryEnter, GenericScopedLock, GenericScopedUnlock
+*/
+template <class LockType>
+class GenericScopedTryLock
+{
+public:
+ //==============================================================================
+ /** Creates a GenericScopedTryLock.
+
+ As soon as it is created, this will attempt to acquire the lock, and when the
+ GenericScopedTryLock is deleted, the lock will be released (if the lock was
+ successfully acquired).
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ inline explicit GenericScopedTryLock (const LockType& lock) noexcept
+ : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {}
+
+ /** Destructor.
+
+ The mutex will be unlocked (if it had been successfully locked) when the
+ destructor is called.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen!
+ */
+ inline ~GenericScopedTryLock() noexcept { if (lockWasSuccessful) lock_.exit(); }
+
+ /** Returns true if the mutex was successfully locked. */
+ bool isLocked() const noexcept { return lockWasSuccessful; }
+
+private:
+ //==============================================================================
+ const LockType& lock_;
+ const bool lockWasSuccessful;
+
+ JUCE_DECLARE_NON_COPYABLE (GenericScopedTryLock)
+};
+
+
+#endif // JUCE_SCOPEDLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedReadLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedReadLock.h
new file mode 100644
index 0000000..107e838
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedReadLock.h
@@ -0,0 +1,90 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SCOPEDREADLOCK_H_INCLUDED
+#define JUCE_SCOPEDREADLOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Automatically locks and unlocks a ReadWriteLock object.
+
+ Use one of these as a local variable to control access to a ReadWriteLock.
+
+ e.g. @code
+
+ ReadWriteLock myLock;
+
+ for (;;)
+ {
+ const ScopedReadLock myScopedLock (myLock);
+ // myLock is now locked
+
+ ...do some stuff...
+
+ // myLock gets unlocked here.
+ }
+ @endcode
+
+ @see ReadWriteLock, ScopedWriteLock
+*/
+class JUCE_API ScopedReadLock
+{
+public:
+ //==============================================================================
+ /** Creates a ScopedReadLock.
+
+ As soon as it is created, this will call ReadWriteLock::enterRead(), and
+ when the ScopedReadLock object is deleted, the ReadWriteLock will
+ be unlocked.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ inline explicit ScopedReadLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterRead(); }
+
+ /** Destructor.
+
+ The ReadWriteLock's exitRead() method will be called when the destructor is called.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen!
+ */
+ inline ~ScopedReadLock() noexcept { lock_.exitRead(); }
+
+
+private:
+ //==============================================================================
+ const ReadWriteLock& lock_;
+
+ JUCE_DECLARE_NON_COPYABLE (ScopedReadLock)
+};
+
+
+#endif // JUCE_SCOPEDREADLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedWriteLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedWriteLock.h
new file mode 100644
index 0000000..44e3198
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ScopedWriteLock.h
@@ -0,0 +1,90 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SCOPEDWRITELOCK_H_INCLUDED
+#define JUCE_SCOPEDWRITELOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Automatically locks and unlocks a ReadWriteLock object.
+
+ Use one of these as a local variable to control access to a ReadWriteLock.
+
+ e.g. @code
+
+ ReadWriteLock myLock;
+
+ for (;;)
+ {
+ const ScopedWriteLock myScopedLock (myLock);
+ // myLock is now locked
+
+ ...do some stuff...
+
+ // myLock gets unlocked here.
+ }
+ @endcode
+
+ @see ReadWriteLock, ScopedReadLock
+*/
+class JUCE_API ScopedWriteLock
+{
+public:
+ //==============================================================================
+ /** Creates a ScopedWriteLock.
+
+ As soon as it is created, this will call ReadWriteLock::enterWrite(), and
+ when the ScopedWriteLock object is deleted, the ReadWriteLock will
+ be unlocked.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen! Best just to use it
+ as a local stack object, rather than creating one with the new() operator.
+ */
+ inline explicit ScopedWriteLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterWrite(); }
+
+ /** Destructor.
+
+ The ReadWriteLock's exitWrite() method will be called when the destructor is called.
+
+ Make sure this object is created and deleted by the same thread,
+ otherwise there are no guarantees what will happen!
+ */
+ inline ~ScopedWriteLock() noexcept { lock_.exitWrite(); }
+
+
+private:
+ //==============================================================================
+ const ReadWriteLock& lock_;
+
+ JUCE_DECLARE_NON_COPYABLE (ScopedWriteLock)
+};
+
+
+#endif // JUCE_SCOPEDWRITELOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_SpinLock.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_SpinLock.h
new file mode 100644
index 0000000..664cc3c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_SpinLock.h
@@ -0,0 +1,91 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_SPINLOCK_H_INCLUDED
+#define JUCE_SPINLOCK_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A simple spin-lock class that can be used as a simple, low-overhead mutex for
+ uncontended situations.
+
+ Note that unlike a CriticalSection, this type of lock is not re-entrant, and may
+ be less efficient when used it a highly contended situation, but it's very small and
+ requires almost no initialisation.
+ It's most appropriate for simple situations where you're only going to hold the
+ lock for a very brief time.
+
+ @see CriticalSection
+*/
+class JUCE_API SpinLock
+{
+public:
+ inline SpinLock() noexcept {}
+ inline ~SpinLock() noexcept {}
+
+ /** Acquires the lock.
+ This will block until the lock has been successfully acquired by this thread.
+ Note that a SpinLock is NOT re-entrant, and is not smart enough to know whether the
+ caller thread already has the lock - so if a thread tries to acquire a lock that it
+ already holds, this method will never return!
+
+ It's strongly recommended that you never call this method directly - instead use the
+ ScopedLockType class to manage the locking using an RAII pattern instead.
+ */
+ void enter() const noexcept;
+
+ /** Attempts to acquire the lock, returning true if this was successful. */
+ inline bool tryEnter() const noexcept
+ {
+ return lock.compareAndSetBool (1, 0);
+ }
+
+ /** Releases the lock. */
+ inline void exit() const noexcept
+ {
+ jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held!
+ lock = 0;
+ }
+
+ //==============================================================================
+ /** Provides the type of scoped lock to use for locking a SpinLock. */
+ typedef GenericScopedLock <SpinLock> ScopedLockType;
+
+ /** Provides the type of scoped unlocker to use with a SpinLock. */
+ typedef GenericScopedUnlock <SpinLock> ScopedUnlockType;
+
+private:
+ //==============================================================================
+ mutable Atomic<int> lock;
+
+ JUCE_DECLARE_NON_COPYABLE (SpinLock)
+};
+
+
+#endif // JUCE_SPINLOCK_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.cpp
new file mode 100644
index 0000000..3d1ff0a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.cpp
@@ -0,0 +1,371 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+Thread::Thread (const String& threadName_)
+ : threadName (threadName_),
+ threadHandle (nullptr),
+ threadId (0),
+ threadPriority (5),
+ affinityMask (0),
+ shouldExit (false)
+{
+}
+
+Thread::~Thread()
+{
+ /* If your thread class's destructor has been called without first stopping the thread, that
+ means that this partially destructed object is still performing some work - and that's
+ probably a Bad Thing!
+
+ To avoid this type of nastiness, always make sure you call stopThread() before or during
+ your subclass's destructor.
+ */
+ jassert (! isThreadRunning());
+
+ stopThread (-1);
+}
+
+//==============================================================================
+// Use a ref-counted object to hold this shared data, so that it can outlive its static
+// shared pointer when threads are still running during static shutdown.
+struct CurrentThreadHolder : public ReferenceCountedObject
+{
+ CurrentThreadHolder() noexcept {}
+
+ typedef ReferenceCountedObjectPtr <CurrentThreadHolder> Ptr;
+ ThreadLocalValue<Thread*> value;
+
+ JUCE_DECLARE_NON_COPYABLE (CurrentThreadHolder)
+};
+
+static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros).
+
+static SpinLock* castToSpinLockWithoutAliasingWarning (void* s)
+{
+ return static_cast<SpinLock*> (s);
+}
+
+static CurrentThreadHolder::Ptr getCurrentThreadHolder()
+{
+ static CurrentThreadHolder::Ptr currentThreadHolder;
+ SpinLock::ScopedLockType lock (*castToSpinLockWithoutAliasingWarning (currentThreadHolderLock));
+
+ if (currentThreadHolder == nullptr)
+ currentThreadHolder = new CurrentThreadHolder();
+
+ return currentThreadHolder;
+}
+
+void Thread::threadEntryPoint()
+{
+ const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
+ currentThreadHolder->value = this;
+
+ JUCE_TRY
+ {
+ if (threadName.isNotEmpty())
+ setCurrentThreadName (threadName);
+
+ if (startSuspensionEvent.wait (10000))
+ {
+ jassert (getCurrentThreadId() == threadId);
+
+ if (affinityMask != 0)
+ setCurrentThreadAffinityMask (affinityMask);
+
+ run();
+ }
+ }
+ JUCE_CATCH_ALL_ASSERT
+
+ currentThreadHolder->value.releaseCurrentThreadStorage();
+ closeThreadHandle();
+}
+
+// used to wrap the incoming call from the platform-specific code
+void JUCE_API juce_threadEntryPoint (void* userData)
+{
+ static_cast <Thread*> (userData)->threadEntryPoint();
+}
+
+//==============================================================================
+void Thread::startThread()
+{
+ const ScopedLock sl (startStopLock);
+
+ shouldExit = false;
+
+ if (threadHandle == nullptr)
+ {
+ launchThread();
+ setThreadPriority (threadHandle, threadPriority);
+ startSuspensionEvent.signal();
+ }
+}
+
+void Thread::startThread (const int priority)
+{
+ const ScopedLock sl (startStopLock);
+
+ if (threadHandle == nullptr)
+ {
+ threadPriority = priority;
+ startThread();
+ }
+ else
+ {
+ setPriority (priority);
+ }
+}
+
+bool Thread::isThreadRunning() const
+{
+ return threadHandle != nullptr;
+}
+
+Thread* JUCE_CALLTYPE Thread::getCurrentThread()
+{
+ return getCurrentThreadHolder()->value.get();
+}
+
+//==============================================================================
+void Thread::signalThreadShouldExit()
+{
+ shouldExit = true;
+}
+
+bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const
+{
+ // Doh! So how exactly do you expect this thread to wait for itself to stop??
+ jassert (getThreadId() != getCurrentThreadId() || getCurrentThreadId() == 0);
+
+ const uint32 timeoutEnd = Time::getMillisecondCounter() + (uint32) timeOutMilliseconds;
+
+ while (isThreadRunning())
+ {
+ if (timeOutMilliseconds >= 0 && Time::getMillisecondCounter() > timeoutEnd)
+ return false;
+
+ sleep (2);
+ }
+
+ return true;
+}
+
+bool Thread::stopThread (const int timeOutMilliseconds)
+{
+ // agh! You can't stop the thread that's calling this method! How on earth
+ // would that work??
+ jassert (getCurrentThreadId() != getThreadId());
+
+ const ScopedLock sl (startStopLock);
+
+ if (isThreadRunning())
+ {
+ signalThreadShouldExit();
+ notify();
+
+ if (timeOutMilliseconds != 0)
+ waitForThreadToExit (timeOutMilliseconds);
+
+ if (isThreadRunning())
+ {
+ // very bad karma if this point is reached, as there are bound to be
+ // locks and events left in silly states when a thread is killed by force..
+ jassertfalse;
+ Logger::writeToLog ("!! killing thread by force !!");
+
+ killThread();
+
+ threadHandle = nullptr;
+ threadId = 0;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//==============================================================================
+bool Thread::setPriority (const int newPriority)
+{
+ // NB: deadlock possible if you try to set the thread prio from the thread itself,
+ // so using setCurrentThreadPriority instead in that case.
+ if (getCurrentThreadId() == getThreadId())
+ return setCurrentThreadPriority (newPriority);
+
+ const ScopedLock sl (startStopLock);
+
+ if ((! isThreadRunning()) || setThreadPriority (threadHandle, newPriority))
+ {
+ threadPriority = newPriority;
+ return true;
+ }
+
+ return false;
+}
+
+bool Thread::setCurrentThreadPriority (const int newPriority)
+{
+ return setThreadPriority (0, newPriority);
+}
+
+void Thread::setAffinityMask (const uint32 newAffinityMask)
+{
+ affinityMask = newAffinityMask;
+}
+
+//==============================================================================
+bool Thread::wait (const int timeOutMilliseconds) const
+{
+ return defaultEvent.wait (timeOutMilliseconds);
+}
+
+void Thread::notify() const
+{
+ defaultEvent.signal();
+}
+
+//==============================================================================
+void SpinLock::enter() const noexcept
+{
+ if (! tryEnter())
+ {
+ for (int i = 20; --i >= 0;)
+ if (tryEnter())
+ return;
+
+ while (! tryEnter())
+ Thread::yield();
+ }
+}
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class AtomicTests : public UnitTest
+{
+public:
+ AtomicTests() : UnitTest ("Atomics") {}
+
+ void runTest()
+ {
+ beginTest ("Misc");
+
+ char a1[7];
+ expect (numElementsInArray(a1) == 7);
+ int a2[3];
+ expect (numElementsInArray(a2) == 3);
+
+ expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
+ expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
+ expect (ByteOrder::swap ((uint64) 0x1122334455667788ULL) == 0x8877665544332211LL);
+
+ beginTest ("Atomic int");
+ AtomicTester <int>::testInteger (*this);
+ beginTest ("Atomic unsigned int");
+ AtomicTester <unsigned int>::testInteger (*this);
+ beginTest ("Atomic int32");
+ AtomicTester <int32>::testInteger (*this);
+ beginTest ("Atomic uint32");
+ AtomicTester <uint32>::testInteger (*this);
+ beginTest ("Atomic long");
+ AtomicTester <long>::testInteger (*this);
+ beginTest ("Atomic void*");
+ AtomicTester <void*>::testInteger (*this);
+ beginTest ("Atomic int*");
+ AtomicTester <int*>::testInteger (*this);
+ beginTest ("Atomic float");
+ AtomicTester <float>::testFloat (*this);
+ #if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
+ beginTest ("Atomic int64");
+ AtomicTester <int64>::testInteger (*this);
+ beginTest ("Atomic uint64");
+ AtomicTester <uint64>::testInteger (*this);
+ beginTest ("Atomic double");
+ AtomicTester <double>::testFloat (*this);
+ #endif
+ }
+
+ template <typename Type>
+ class AtomicTester
+ {
+ public:
+ AtomicTester() {}
+
+ static void testInteger (UnitTest& test)
+ {
+ Atomic<Type> a, b;
+ a.set ((Type) 10);
+ test.expect (a.value == (Type) 10);
+ test.expect (a.get() == (Type) 10);
+ a += (Type) 15;
+ test.expect (a.get() == (Type) 25);
+ a.memoryBarrier();
+ a -= (Type) 5;
+ test.expect (a.get() == (Type) 20);
+ test.expect (++a == (Type) 21);
+ ++a;
+ test.expect (--a == (Type) 21);
+ test.expect (a.get() == (Type) 21);
+ a.memoryBarrier();
+
+ testFloat (test);
+ }
+
+ static void testFloat (UnitTest& test)
+ {
+ Atomic<Type> a, b;
+ a = (Type) 21;
+ a.memoryBarrier();
+
+ /* These are some simple test cases to check the atomics - let me know
+ if any of these assertions fail on your system!
+ */
+ test.expect (a.get() == (Type) 21);
+ test.expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
+ test.expect (a.get() == (Type) 21);
+ test.expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
+ test.expect (a.get() == (Type) 101);
+ test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
+ test.expect (a.get() == (Type) 101);
+ test.expect (a.compareAndSetBool ((Type) 200, a.get()));
+ test.expect (a.get() == (Type) 200);
+
+ test.expect (a.exchange ((Type) 300) == (Type) 200);
+ test.expect (a.get() == (Type) 300);
+
+ b = a;
+ test.expect (b.get() == a.get());
+ }
+ };
+};
+
+static AtomicTests atomicUnitTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.h
new file mode 100644
index 0000000..aef96b7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_Thread.h
@@ -0,0 +1,289 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_THREAD_H_INCLUDED
+#define JUCE_THREAD_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Encapsulates a thread.
+
+ Subclasses derive from Thread and implement the run() method, in which they
+ do their business. The thread can then be started with the startThread() method
+ and controlled with various other methods.
+
+ This class also contains some thread-related static methods, such
+ as sleep(), yield(), getCurrentThreadId() etc.
+
+ @see CriticalSection, WaitableEvent, Process, ThreadWithProgressWindow,
+ MessageManagerLock
+*/
+class JUCE_API Thread
+{
+public:
+ //==============================================================================
+ /**
+ Creates a thread.
+
+ When first created, the thread is not running. Use the startThread()
+ method to start it.
+ */
+ explicit Thread (const String& threadName);
+
+ /** Destructor.
+
+ You must never attempt to delete a Thread object while it's still running -
+ always call stopThread() and make sure your thread has stopped before deleting
+ the object. Failing to do so will throw an assertion, and put you firmly into
+ undefined behaviour territory.
+ */
+ virtual ~Thread();
+
+ //==============================================================================
+ /** Must be implemented to perform the thread's actual code.
+
+ Remember that the thread must regularly check the threadShouldExit()
+ method whilst running, and if this returns true it should return from
+ the run() method as soon as possible to avoid being forcibly killed.
+
+ @see threadShouldExit, startThread
+ */
+ virtual void run() = 0;
+
+ //==============================================================================
+ // Thread control functions..
+
+ /** Starts the thread running.
+
+ This will cause the thread's run() method to be called by a new thread.
+ If this thread is already running, startThread() won't do anything.
+
+ @see stopThread
+ */
+ void startThread();
+
+ /** Starts the thread with a given priority.
+
+ Launches the thread with a given priority, where 0 = lowest, 10 = highest.
+ If the thread is already running, its priority will be changed.
+
+ @see startThread, setPriority
+ */
+ void startThread (int priority);
+
+ /** Attempts to stop the thread running.
+
+ This method will cause the threadShouldExit() method to return true
+ and call notify() in case the thread is currently waiting.
+
+ Hopefully the thread will then respond to this by exiting cleanly, and
+ the stopThread method will wait for a given time-period for this to
+ happen.
+
+ If the thread is stuck and fails to respond after the time-out, it gets
+ forcibly killed, which is a very bad thing to happen, as it could still
+ be holding locks, etc. which are needed by other parts of your program.
+
+ @param timeOutMilliseconds The number of milliseconds to wait for the
+ thread to finish before killing it by force. A negative
+ value in here will wait forever.
+ @returns true if the thread was cleanly stopped before the timeout, or false
+ if it had to be killed by force.
+ @see signalThreadShouldExit, threadShouldExit, waitForThreadToExit, isThreadRunning
+ */
+ bool stopThread (int timeOutMilliseconds);
+
+ //==============================================================================
+ /** Returns true if the thread is currently active */
+ bool isThreadRunning() const;
+
+ /** Sets a flag to tell the thread it should stop.
+
+ Calling this means that the threadShouldExit() method will then return true.
+ The thread should be regularly checking this to see whether it should exit.
+
+ If your thread makes use of wait(), you might want to call notify() after calling
+ this method, to interrupt any waits that might be in progress, and allow it
+ to reach a point where it can exit.
+
+ @see threadShouldExit
+ @see waitForThreadToExit
+ */
+ void signalThreadShouldExit();
+
+ /** Checks whether the thread has been told to stop running.
+
+ Threads need to check this regularly, and if it returns true, they should
+ return from their run() method at the first possible opportunity.
+
+ @see signalThreadShouldExit
+ */
+ inline bool threadShouldExit() const { return shouldExit; }
+
+ /** Waits for the thread to stop.
+
+ This will waits until isThreadRunning() is false or until a timeout expires.
+
+ @param timeOutMilliseconds the time to wait, in milliseconds. If this value
+ is less than zero, it will wait forever.
+ @returns true if the thread exits, or false if the timeout expires first.
+ */
+ bool waitForThreadToExit (int timeOutMilliseconds) const;
+
+ //==============================================================================
+ /** Changes the thread's priority.
+ May return false if for some reason the priority can't be changed.
+
+ @param priority the new priority, in the range 0 (lowest) to 10 (highest). A priority
+ of 5 is normal.
+ */
+ bool setPriority (int priority);
+
+ /** Changes the priority of the caller thread.
+
+ Similar to setPriority(), but this static method acts on the caller thread.
+ May return false if for some reason the priority can't be changed.
+
+ @see setPriority
+ */
+ static bool setCurrentThreadPriority (int priority);
+
+ //==============================================================================
+ /** Sets the affinity mask for the thread.
+
+ This will only have an effect next time the thread is started - i.e. if the
+ thread is already running when called, it'll have no effect.
+
+ @see setCurrentThreadAffinityMask
+ */
+ void setAffinityMask (uint32 affinityMask);
+
+ /** Changes the affinity mask for the caller thread.
+ This will change the affinity mask for the thread that calls this static method.
+ @see setAffinityMask
+ */
+ static void JUCE_CALLTYPE setCurrentThreadAffinityMask (uint32 affinityMask);
+
+ //==============================================================================
+ // this can be called from any thread that needs to pause..
+ static void JUCE_CALLTYPE sleep (int milliseconds);
+
+ /** Yields the calling thread's current time-slot. */
+ static void JUCE_CALLTYPE yield();
+
+ //==============================================================================
+ /** Makes the thread wait for a notification.
+
+ This puts the thread to sleep until either the timeout period expires, or
+ another thread calls the notify() method to wake it up.
+
+ A negative time-out value means that the method will wait indefinitely.
+
+ @returns true if the event has been signalled, false if the timeout expires.
+ */
+ bool wait (int timeOutMilliseconds) const;
+
+ /** Wakes up the thread.
+
+ If the thread has called the wait() method, this will wake it up.
+
+ @see wait
+ */
+ void notify() const;
+
+ //==============================================================================
+ /** A value type used for thread IDs.
+ @see getCurrentThreadId(), getThreadId()
+ */
+ typedef void* ThreadID;
+
+ /** Returns an id that identifies the caller thread.
+
+ To find the ID of a particular thread object, use getThreadId().
+
+ @returns a unique identifier that identifies the calling thread.
+ @see getThreadId
+ */
+ static ThreadID JUCE_CALLTYPE getCurrentThreadId();
+
+ /** Finds the thread object that is currently running.
+
+ Note that the main UI thread (or other non-Juce threads) don't have a Thread
+ object associated with them, so this will return 0.
+ */
+ static Thread* JUCE_CALLTYPE getCurrentThread();
+
+ /** Returns the ID of this thread.
+
+ That means the ID of this thread object - not of the thread that's calling the method.
+
+ This can change when the thread is started and stopped, and will be invalid if the
+ thread's not actually running.
+
+ @see getCurrentThreadId
+ */
+ ThreadID getThreadId() const noexcept { return threadId; }
+
+ /** Returns the name of the thread.
+
+ This is the name that gets set in the constructor.
+ */
+ const String& getThreadName() const { return threadName; }
+
+ /** Changes the name of the caller thread.
+ Different OSes may place different length or content limits on this name.
+ */
+ static void JUCE_CALLTYPE setCurrentThreadName (const String& newThreadName);
+
+
+private:
+ //==============================================================================
+ const String threadName;
+ void* volatile threadHandle;
+ ThreadID threadId;
+ CriticalSection startStopLock;
+ WaitableEvent startSuspensionEvent, defaultEvent;
+ int threadPriority;
+ uint32 affinityMask;
+ bool volatile shouldExit;
+
+ #ifndef DOXYGEN
+ friend void JUCE_API juce_threadEntryPoint (void*);
+ #endif
+
+ void launchThread();
+ void closeThreadHandle();
+ void killThread();
+ void threadEntryPoint();
+ static bool setThreadPriority (void*, int);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Thread)
+};
+
+#endif // JUCE_THREAD_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadLocalValue.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadLocalValue.h
new file mode 100644
index 0000000..bd5c808
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadLocalValue.h
@@ -0,0 +1,198 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_THREADLOCALVALUE_H_INCLUDED
+#define JUCE_THREADLOCALVALUE_H_INCLUDED
+
+// (NB: on win32, native thread-locals aren't possible in a dynamically loaded DLL in XP).
+#if ! ((JUCE_MSVC && (JUCE_64BIT || ! defined (JucePlugin_PluginCode))) \
+ || (JUCE_MAC && JUCE_CLANG && defined (MAC_OS_X_VERSION_10_7) \
+ && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7))
+ #define JUCE_NO_COMPILER_THREAD_LOCAL 1
+#endif
+
+//==============================================================================
+/**
+ Provides cross-platform support for thread-local objects.
+
+ This class holds an internal list of objects of the templated type, keeping
+ an instance for each thread that requests one. The first time a thread attempts
+ to access its value, an object is created and added to the list for that thread.
+
+ Typically, you'll probably want to create a static instance of a ThreadLocalValue
+ object, or hold one within a singleton.
+
+ The templated class for your value must be a primitive type, or a simple POD struct.
+
+ When a thread no longer needs to use its value, it can call releaseCurrentThreadStorage()
+ to allow the storage to be re-used by another thread. If a thread exits without calling
+ this method, the object storage will be left allocated until the ThreadLocalValue object
+ is deleted.
+*/
+template <typename Type>
+class ThreadLocalValue
+{
+public:
+ /** */
+ ThreadLocalValue() noexcept
+ {
+ }
+
+ /** Destructor.
+ When this object is deleted, all the value objects for all threads will be deleted.
+ */
+ ~ThreadLocalValue()
+ {
+ #if JUCE_NO_COMPILER_THREAD_LOCAL
+ for (ObjectHolder* o = first.value; o != nullptr;)
+ {
+ ObjectHolder* const next = o->next;
+ delete o;
+ o = next;
+ }
+ #endif
+ }
+
+ /** Returns a reference to this thread's instance of the value.
+ Note that the first time a thread tries to access the value, an instance of the
+ value object will be created - so if your value's class has a non-trivial
+ constructor, be aware that this method could invoke it.
+ */
+ Type& operator*() const noexcept { return get(); }
+
+ /** Returns a pointer to this thread's instance of the value.
+ Note that the first time a thread tries to access the value, an instance of the
+ value object will be created - so if your value's class has a non-trivial
+ constructor, be aware that this method could invoke it.
+ */
+ operator Type*() const noexcept { return &get(); }
+
+ /** Accesses a method or field of the value object.
+ Note that the first time a thread tries to access the value, an instance of the
+ value object will be created - so if your value's class has a non-trivial
+ constructor, be aware that this method could invoke it.
+ */
+ Type* operator->() const noexcept { return &get(); }
+
+ /** Assigns a new value to the thread-local object. */
+ ThreadLocalValue& operator= (const Type& newValue) { get() = newValue; return *this; }
+
+ /** Returns a reference to this thread's instance of the value.
+ Note that the first time a thread tries to access the value, an instance of the
+ value object will be created - so if your value's class has a non-trivial
+ constructor, be aware that this method could invoke it.
+ */
+ Type& get() const noexcept
+ {
+ #if JUCE_NO_COMPILER_THREAD_LOCAL
+ const Thread::ThreadID threadId = Thread::getCurrentThreadId();
+
+ for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
+ if (o->threadId == threadId)
+ return o->object;
+
+ for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
+ {
+ if (o->threadId == nullptr)
+ {
+ {
+ SpinLock::ScopedLockType sl (lock);
+
+ if (o->threadId != nullptr)
+ continue;
+
+ o->threadId = threadId;
+ }
+
+ o->object = Type();
+ return o->object;
+ }
+ }
+
+ ObjectHolder* const newObject = new ObjectHolder (threadId);
+
+ do
+ {
+ newObject->next = first.get();
+ }
+ while (! first.compareAndSetBool (newObject, newObject->next));
+
+ return newObject->object;
+ #elif JUCE_MAC
+ static __thread Type object;
+ return object;
+ #elif JUCE_MSVC
+ static __declspec(thread) Type object;
+ return object;
+ #endif
+ }
+
+ /** Called by a thread before it terminates, to allow this class to release
+ any storage associated with the thread.
+ */
+ void releaseCurrentThreadStorage()
+ {
+ #if JUCE_NO_COMPILER_THREAD_LOCAL
+ const Thread::ThreadID threadId = Thread::getCurrentThreadId();
+
+ for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
+ {
+ if (o->threadId == threadId)
+ {
+ SpinLock::ScopedLockType sl (lock);
+ o->threadId = nullptr;
+ }
+ }
+ #endif
+ }
+
+private:
+ //==============================================================================
+ #if JUCE_NO_COMPILER_THREAD_LOCAL
+ struct ObjectHolder
+ {
+ ObjectHolder (const Thread::ThreadID& tid)
+ : threadId (tid), next (nullptr), object()
+ {}
+
+ Thread::ThreadID threadId;
+ ObjectHolder* next;
+ Type object;
+
+ JUCE_DECLARE_NON_COPYABLE (ObjectHolder)
+ };
+
+ mutable Atomic<ObjectHolder*> first;
+ SpinLock lock;
+ #endif
+
+ JUCE_DECLARE_NON_COPYABLE (ThreadLocalValue)
+};
+
+
+#endif // JUCE_THREADLOCALVALUE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.cpp
new file mode 100644
index 0000000..e6b0b9f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.cpp
@@ -0,0 +1,384 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class ThreadPool::ThreadPoolThread : public Thread
+{
+public:
+ ThreadPoolThread (ThreadPool& p)
+ : Thread ("Pool"), currentJob (nullptr), pool (p)
+ {
+ }
+
+ void run() override
+ {
+ while (! threadShouldExit())
+ if (! pool.runNextJob (*this))
+ wait (500);
+ }
+
+ ThreadPoolJob* volatile currentJob;
+ ThreadPool& pool;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolThread)
+};
+
+//==============================================================================
+ThreadPoolJob::ThreadPoolJob (const String& name)
+ : jobName (name), pool (nullptr),
+ shouldStop (false), isActive (false), shouldBeDeleted (false)
+{
+}
+
+ThreadPoolJob::~ThreadPoolJob()
+{
+ // you mustn't delete a job while it's still in a pool! Use ThreadPool::removeJob()
+ // to remove it first!
+ jassert (pool == nullptr || ! pool->contains (this));
+}
+
+String ThreadPoolJob::getJobName() const
+{
+ return jobName;
+}
+
+void ThreadPoolJob::setJobName (const String& newName)
+{
+ jobName = newName;
+}
+
+void ThreadPoolJob::signalJobShouldExit()
+{
+ shouldStop = true;
+}
+
+ThreadPoolJob* ThreadPoolJob::getCurrentThreadPoolJob()
+{
+ if (ThreadPool::ThreadPoolThread* t = dynamic_cast<ThreadPool::ThreadPoolThread*> (Thread::getCurrentThread()))
+ return t->currentJob;
+
+ return nullptr;
+}
+
+//==============================================================================
+ThreadPool::ThreadPool (const int numThreads)
+{
+ jassert (numThreads > 0); // not much point having a pool without any threads!
+
+ createThreads (numThreads);
+}
+
+ThreadPool::ThreadPool()
+{
+ createThreads (SystemStats::getNumCpus());
+}
+
+ThreadPool::~ThreadPool()
+{
+ removeAllJobs (true, 5000);
+ stopThreads();
+}
+
+void ThreadPool::createThreads (int numThreads)
+{
+ for (int i = jmax (1, numThreads); --i >= 0;)
+ threads.add (new ThreadPoolThread (*this));
+
+ for (int i = threads.size(); --i >= 0;)
+ threads.getUnchecked(i)->startThread();
+}
+
+void ThreadPool::stopThreads()
+{
+ for (int i = threads.size(); --i >= 0;)
+ threads.getUnchecked(i)->signalThreadShouldExit();
+
+ for (int i = threads.size(); --i >= 0;)
+ threads.getUnchecked(i)->stopThread (500);
+}
+
+void ThreadPool::addJob (ThreadPoolJob* const job, const bool deleteJobWhenFinished)
+{
+ jassert (job != nullptr);
+ jassert (job->pool == nullptr);
+
+ if (job->pool == nullptr)
+ {
+ job->pool = this;
+ job->shouldStop = false;
+ job->isActive = false;
+ job->shouldBeDeleted = deleteJobWhenFinished;
+
+ {
+ const ScopedLock sl (lock);
+ jobs.add (job);
+ }
+
+ for (int i = threads.size(); --i >= 0;)
+ threads.getUnchecked(i)->notify();
+ }
+}
+
+int ThreadPool::getNumJobs() const
+{
+ return jobs.size();
+}
+
+ThreadPoolJob* ThreadPool::getJob (const int index) const
+{
+ const ScopedLock sl (lock);
+ return jobs [index];
+}
+
+bool ThreadPool::contains (const ThreadPoolJob* const job) const
+{
+ const ScopedLock sl (lock);
+ return jobs.contains (const_cast <ThreadPoolJob*> (job));
+}
+
+bool ThreadPool::isJobRunning (const ThreadPoolJob* const job) const
+{
+ const ScopedLock sl (lock);
+ return jobs.contains (const_cast <ThreadPoolJob*> (job)) && job->isActive;
+}
+
+bool ThreadPool::waitForJobToFinish (const ThreadPoolJob* const job, const int timeOutMs) const
+{
+ if (job != nullptr)
+ {
+ const uint32 start = Time::getMillisecondCounter();
+
+ while (contains (job))
+ {
+ if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + (uint32) timeOutMs)
+ return false;
+
+ jobFinishedSignal.wait (2);
+ }
+ }
+
+ return true;
+}
+
+bool ThreadPool::removeJob (ThreadPoolJob* const job,
+ const bool interruptIfRunning,
+ const int timeOutMs)
+{
+ bool dontWait = true;
+ OwnedArray<ThreadPoolJob> deletionList;
+
+ if (job != nullptr)
+ {
+ const ScopedLock sl (lock);
+
+ if (jobs.contains (job))
+ {
+ if (job->isActive)
+ {
+ if (interruptIfRunning)
+ job->signalJobShouldExit();
+
+ dontWait = false;
+ }
+ else
+ {
+ jobs.removeFirstMatchingValue (job);
+ addToDeleteList (deletionList, job);
+ }
+ }
+ }
+
+ return dontWait || waitForJobToFinish (job, timeOutMs);
+}
+
+bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, const int timeOutMs,
+ ThreadPool::JobSelector* const selectedJobsToRemove)
+{
+ Array <ThreadPoolJob*> jobsToWaitFor;
+
+ {
+ OwnedArray<ThreadPoolJob> deletionList;
+
+ {
+ const ScopedLock sl (lock);
+
+ for (int i = jobs.size(); --i >= 0;)
+ {
+ ThreadPoolJob* const job = jobs.getUnchecked(i);
+
+ if (selectedJobsToRemove == nullptr || selectedJobsToRemove->isJobSuitable (job))
+ {
+ if (job->isActive)
+ {
+ jobsToWaitFor.add (job);
+
+ if (interruptRunningJobs)
+ job->signalJobShouldExit();
+ }
+ else
+ {
+ jobs.remove (i);
+ addToDeleteList (deletionList, job);
+ }
+ }
+ }
+ }
+ }
+
+ const uint32 start = Time::getMillisecondCounter();
+
+ for (;;)
+ {
+ for (int i = jobsToWaitFor.size(); --i >= 0;)
+ {
+ ThreadPoolJob* const job = jobsToWaitFor.getUnchecked (i);
+
+ if (! isJobRunning (job))
+ jobsToWaitFor.remove (i);
+ }
+
+ if (jobsToWaitFor.size() == 0)
+ break;
+
+ if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + (uint32) timeOutMs)
+ return false;
+
+ jobFinishedSignal.wait (20);
+ }
+
+ return true;
+}
+
+StringArray ThreadPool::getNamesOfAllJobs (const bool onlyReturnActiveJobs) const
+{
+ StringArray s;
+ const ScopedLock sl (lock);
+
+ for (int i = 0; i < jobs.size(); ++i)
+ {
+ const ThreadPoolJob* const job = jobs.getUnchecked(i);
+ if (job->isActive || ! onlyReturnActiveJobs)
+ s.add (job->getJobName());
+ }
+
+ return s;
+}
+
+bool ThreadPool::setThreadPriorities (const int newPriority)
+{
+ bool ok = true;
+
+ for (int i = threads.size(); --i >= 0;)
+ if (! threads.getUnchecked(i)->setPriority (newPriority))
+ ok = false;
+
+ return ok;
+}
+
+ThreadPoolJob* ThreadPool::pickNextJobToRun()
+{
+ OwnedArray<ThreadPoolJob> deletionList;
+
+ {
+ const ScopedLock sl (lock);
+
+ for (int i = 0; i < jobs.size(); ++i)
+ {
+ ThreadPoolJob* job = jobs[i];
+
+ if (job != nullptr && ! job->isActive)
+ {
+ if (job->shouldStop)
+ {
+ jobs.remove (i);
+ addToDeleteList (deletionList, job);
+ --i;
+ continue;
+ }
+
+ job->isActive = true;
+ return job;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+bool ThreadPool::runNextJob (ThreadPoolThread& thread)
+{
+ if (ThreadPoolJob* const job = pickNextJobToRun())
+ {
+ ThreadPoolJob::JobStatus result = ThreadPoolJob::jobHasFinished;
+ thread.currentJob = job;
+
+ JUCE_TRY
+ {
+ result = job->runJob();
+ }
+ JUCE_CATCH_ALL_ASSERT
+
+ thread.currentJob = nullptr;
+
+ OwnedArray<ThreadPoolJob> deletionList;
+
+ {
+ const ScopedLock sl (lock);
+
+ if (jobs.contains (job))
+ {
+ job->isActive = false;
+
+ if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop)
+ {
+ jobs.removeFirstMatchingValue (job);
+ addToDeleteList (deletionList, job);
+
+ jobFinishedSignal.signal();
+ }
+ else
+ {
+ // move the job to the end of the queue if it wants another go
+ jobs.move (jobs.indexOf (job), -1);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void ThreadPool::addToDeleteList (OwnedArray<ThreadPoolJob>& deletionList, ThreadPoolJob* const job) const
+{
+ job->shouldStop = true;
+ job->pool = nullptr;
+
+ if (job->shouldBeDeleted)
+ deletionList.add (job);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.h
new file mode 100644
index 0000000..3d5f762
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_ThreadPool.h
@@ -0,0 +1,321 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_THREADPOOL_H_INCLUDED
+#define JUCE_THREADPOOL_H_INCLUDED
+
+class ThreadPool;
+class ThreadPoolThread;
+
+
+//==============================================================================
+/**
+ A task that is executed by a ThreadPool object.
+
+ A ThreadPool keeps a list of ThreadPoolJob objects which are executed by
+ its threads.
+
+ The runJob() method needs to be implemented to do the task, and if the code that
+ does the work takes a significant time to run, it must keep checking the shouldExit()
+ method to see if something is trying to interrupt the job. If shouldExit() returns
+ true, the runJob() method must return immediately.
+
+ @see ThreadPool, Thread
+*/
+class JUCE_API ThreadPoolJob
+{
+public:
+ //==============================================================================
+ /** Creates a thread pool job object.
+ After creating your job, add it to a thread pool with ThreadPool::addJob().
+ */
+ explicit ThreadPoolJob (const String& name);
+
+ /** Destructor. */
+ virtual ~ThreadPoolJob();
+
+ //==============================================================================
+ /** Returns the name of this job.
+ @see setJobName
+ */
+ String getJobName() const;
+
+ /** Changes the job's name.
+ @see getJobName
+ */
+ void setJobName (const String& newName);
+
+ //==============================================================================
+ /** These are the values that can be returned by the runJob() method.
+ */
+ enum JobStatus
+ {
+ jobHasFinished = 0, /**< indicates that the job has finished and can be
+ removed from the pool. */
+
+ jobNeedsRunningAgain /**< indicates that the job would like to be called
+ again when a thread is free. */
+ };
+
+ /** Peforms the actual work that this job needs to do.
+
+ Your subclass must implement this method, in which is does its work.
+
+ If the code in this method takes a significant time to run, it must repeatedly check
+ the shouldExit() method to see if something is trying to interrupt the job.
+ If shouldExit() ever returns true, the runJob() method must return immediately.
+
+ If this method returns jobHasFinished, then the job will be removed from the pool
+ immediately. If it returns jobNeedsRunningAgain, then the job will be left in the
+ pool and will get a chance to run again as soon as a thread is free.
+
+ @see shouldExit()
+ */
+ virtual JobStatus runJob() = 0;
+
+
+ //==============================================================================
+ /** Returns true if this job is currently running its runJob() method. */
+ bool isRunning() const noexcept { return isActive; }
+
+ /** Returns true if something is trying to interrupt this job and make it stop.
+
+ Your runJob() method must call this whenever it gets a chance, and if it ever
+ returns true, the runJob() method must return immediately.
+
+ @see signalJobShouldExit()
+ */
+ bool shouldExit() const noexcept { return shouldStop; }
+
+ /** Calling this will cause the shouldExit() method to return true, and the job
+ should (if it's been implemented correctly) stop as soon as possible.
+
+ @see shouldExit()
+ */
+ void signalJobShouldExit();
+
+ //==============================================================================
+ /** If the calling thread is being invoked inside a runJob() method, this will
+ return the ThreadPoolJob that it belongs to.
+ */
+ static ThreadPoolJob* getCurrentThreadPoolJob();
+
+ //==============================================================================
+private:
+ friend class ThreadPool;
+ friend class ThreadPoolThread;
+ String jobName;
+ ThreadPool* pool;
+ bool shouldStop, isActive, shouldBeDeleted;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolJob)
+};
+
+
+//==============================================================================
+/**
+ A set of threads that will run a list of jobs.
+
+ When a ThreadPoolJob object is added to the ThreadPool's list, its runJob() method
+ will be called by the next pooled thread that becomes free.
+
+ @see ThreadPoolJob, Thread
+*/
+class JUCE_API ThreadPool
+{
+public:
+ //==============================================================================
+ /** Creates a thread pool.
+ Once you've created a pool, you can give it some jobs by calling addJob().
+ @param numberOfThreads the number of threads to run. These will be started
+ immediately, and will run until the pool is deleted.
+ */
+ ThreadPool (int numberOfThreads);
+
+ /** Creates a thread pool with one thread per CPU core.
+ Once you've created a pool, you can give it some jobs by calling addJob().
+ If you want to specify the number of threads, use the other constructor; this
+ one creates a pool which has one thread for each CPU core.
+ @see SystemStats::getNumCpus()
+ */
+ ThreadPool();
+
+ /** Destructor.
+
+ This will attempt to remove all the jobs before deleting, but if you want to
+ specify a timeout, you should call removeAllJobs() explicitly before deleting
+ the pool.
+ */
+ ~ThreadPool();
+
+ //==============================================================================
+ /** A callback class used when you need to select which ThreadPoolJob objects are suitable
+ for some kind of operation.
+ @see ThreadPool::removeAllJobs
+ */
+ class JUCE_API JobSelector
+ {
+ public:
+ virtual ~JobSelector() {}
+
+ /** Should return true if the specified thread matches your criteria for whatever
+ operation that this object is being used for.
+
+ Any implementation of this method must be extremely fast and thread-safe!
+ */
+ virtual bool isJobSuitable (ThreadPoolJob* job) = 0;
+ };
+
+ //==============================================================================
+ /** Adds a job to the queue.
+
+ Once a job has been added, then the next time a thread is free, it will run
+ the job's ThreadPoolJob::runJob() method. Depending on the return value of the
+ runJob() method, the pool will either remove the job from the pool or add it to
+ the back of the queue to be run again.
+
+ If deleteJobWhenFinished is true, then the job object will be owned and deleted by
+ the pool when not needed - if you do this, make sure that your object's destructor
+ is thread-safe.
+
+ If deleteJobWhenFinished is false, the pointer will be used but not deleted, and
+ the caller is responsible for making sure the object is not deleted before it has
+ been removed from the pool.
+ */
+ void addJob (ThreadPoolJob* job,
+ bool deleteJobWhenFinished);
+
+ /** Tries to remove a job from the pool.
+
+ If the job isn't yet running, this will simply remove it. If it is running, it
+ will wait for it to finish.
+
+ If the timeout period expires before the job finishes running, then the job will be
+ left in the pool and this will return false. It returns true if the job is successfully
+ stopped and removed.
+
+ @param job the job to remove
+ @param interruptIfRunning if true, then if the job is currently busy, its
+ ThreadPoolJob::signalJobShouldExit() method will be called to try
+ to interrupt it. If false, then if the job will be allowed to run
+ until it stops normally (or the timeout expires)
+ @param timeOutMilliseconds the length of time this method should wait for the job to finish
+ before giving up and returning false
+ */
+ bool removeJob (ThreadPoolJob* job,
+ bool interruptIfRunning,
+ int timeOutMilliseconds);
+
+ /** Tries to remove all jobs from the pool.
+
+ @param interruptRunningJobs if true, then all running jobs will have their ThreadPoolJob::signalJobShouldExit()
+ methods called to try to interrupt them
+ @param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
+ before giving up and returning false
+ @param selectedJobsToRemove if this is non-zero, the JobSelector object is asked to decide which
+ jobs should be removed. If it is zero, all jobs are removed
+ @returns true if all jobs are successfully stopped and removed; false if the timeout period
+ expires while waiting for one or more jobs to stop
+ */
+ bool removeAllJobs (bool interruptRunningJobs,
+ int timeOutMilliseconds,
+ JobSelector* selectedJobsToRemove = nullptr);
+
+ /** Returns the number of jobs currently running or queued.
+ */
+ int getNumJobs() const;
+
+ /** Returns one of the jobs in the queue.
+
+ Note that this can be a very volatile list as jobs might be continuously getting shifted
+ around in the list, and this method may return nullptr if the index is currently out-of-range.
+ */
+ ThreadPoolJob* getJob (int index) const;
+
+ /** Returns true if the given job is currently queued or running.
+
+ @see isJobRunning()
+ */
+ bool contains (const ThreadPoolJob* job) const;
+
+ /** Returns true if the given job is currently being run by a thread.
+ */
+ bool isJobRunning (const ThreadPoolJob* job) const;
+
+ /** Waits until a job has finished running and has been removed from the pool.
+
+ This will wait until the job is no longer in the pool - i.e. until its
+ runJob() method returns ThreadPoolJob::jobHasFinished.
+
+ If the timeout period expires before the job finishes, this will return false;
+ it returns true if the job has finished successfully.
+ */
+ bool waitForJobToFinish (const ThreadPoolJob* job,
+ int timeOutMilliseconds) const;
+
+ /** Returns a list of the names of all the jobs currently running or queued.
+ If onlyReturnActiveJobs is true, only the ones currently running are returned.
+ */
+ StringArray getNamesOfAllJobs (bool onlyReturnActiveJobs) const;
+
+ /** Changes the priority of all the threads.
+
+ This will call Thread::setPriority() for each thread in the pool.
+ May return false if for some reason the priority can't be changed.
+ */
+ bool setThreadPriorities (int newPriority);
+
+
+private:
+ //==============================================================================
+ Array <ThreadPoolJob*> jobs;
+
+ class ThreadPoolThread;
+ friend class ThreadPoolJob;
+ friend class ThreadPoolThread;
+ friend struct ContainerDeletePolicy<ThreadPoolThread>;
+ OwnedArray<ThreadPoolThread> threads;
+
+ CriticalSection lock;
+ WaitableEvent jobFinishedSignal;
+
+ bool runNextJob (ThreadPoolThread&);
+ ThreadPoolJob* pickNextJobToRun();
+ void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;
+ void createThreads (int numThreads);
+ void stopThreads();
+
+ // Note that this method has changed, and no longer has a parameter to indicate
+ // whether the jobs should be deleted - see the new method for details.
+ void removeAllJobs (bool, int, bool);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPool)
+};
+
+
+#endif // JUCE_THREADPOOL_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.cpp
new file mode 100644
index 0000000..f055a15
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.cpp
@@ -0,0 +1,171 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+TimeSliceThread::TimeSliceThread (const String& name)
+ : Thread (name),
+ clientBeingCalled (nullptr)
+{
+}
+
+TimeSliceThread::~TimeSliceThread()
+{
+ stopThread (2000);
+}
+
+//==============================================================================
+void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client, int millisecondsBeforeStarting)
+{
+ if (client != nullptr)
+ {
+ const ScopedLock sl (listLock);
+ client->nextCallTime = Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting);
+ clients.addIfNotAlreadyThere (client);
+ notify();
+ }
+}
+
+void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client)
+{
+ const ScopedLock sl1 (listLock);
+
+ // if there's a chance we're in the middle of calling this client, we need to
+ // also lock the outer lock..
+ if (clientBeingCalled == client)
+ {
+ const ScopedUnlock ul (listLock); // unlock first to get the order right..
+
+ const ScopedLock sl2 (callbackLock);
+ const ScopedLock sl3 (listLock);
+
+ clients.removeFirstMatchingValue (client);
+ }
+ else
+ {
+ clients.removeFirstMatchingValue (client);
+ }
+}
+
+void TimeSliceThread::moveToFrontOfQueue (TimeSliceClient* client)
+{
+ const ScopedLock sl (listLock);
+
+ if (clients.contains (client))
+ {
+ client->nextCallTime = Time::getCurrentTime();
+ notify();
+ }
+}
+
+int TimeSliceThread::getNumClients() const
+{
+ return clients.size();
+}
+
+TimeSliceClient* TimeSliceThread::getClient (const int i) const
+{
+ const ScopedLock sl (listLock);
+ return clients [i];
+}
+
+//==============================================================================
+TimeSliceClient* TimeSliceThread::getNextClient (int index) const
+{
+ Time soonest;
+ TimeSliceClient* client = nullptr;
+
+ for (int i = clients.size(); --i >= 0;)
+ {
+ TimeSliceClient* const c = clients.getUnchecked ((i + index) % clients.size());
+
+ if (client == nullptr || c->nextCallTime < soonest)
+ {
+ client = c;
+ soonest = c->nextCallTime;
+ }
+ }
+
+ return client;
+}
+
+void TimeSliceThread::run()
+{
+ int index = 0;
+
+ while (! threadShouldExit())
+ {
+ int timeToWait = 500;
+
+ {
+ Time nextClientTime;
+
+ {
+ const ScopedLock sl2 (listLock);
+
+ index = clients.size() > 0 ? ((index + 1) % clients.size()) : 0;
+
+ if (TimeSliceClient* const firstClient = getNextClient (index))
+ nextClientTime = firstClient->nextCallTime;
+ }
+
+ const Time now (Time::getCurrentTime());
+
+ if (nextClientTime > now)
+ {
+ timeToWait = (int) jmin ((int64) 500, (nextClientTime - now).inMilliseconds());
+ }
+ else
+ {
+ timeToWait = index == 0 ? 1 : 0;
+
+ const ScopedLock sl (callbackLock);
+
+ {
+ const ScopedLock sl2 (listLock);
+ clientBeingCalled = getNextClient (index);
+ }
+
+ if (clientBeingCalled != nullptr)
+ {
+ const int msUntilNextCall = clientBeingCalled->useTimeSlice();
+
+ const ScopedLock sl2 (listLock);
+
+ if (msUntilNextCall >= 0)
+ clientBeingCalled->nextCallTime = now + RelativeTime::milliseconds (msUntilNextCall);
+ else
+ clients.removeFirstMatchingValue (clientBeingCalled);
+
+ clientBeingCalled = nullptr;
+ }
+ }
+ }
+
+ if (timeToWait > 0)
+ wait (timeToWait);
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.h
new file mode 100644
index 0000000..8c30567
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_TimeSliceThread.h
@@ -0,0 +1,149 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_TIMESLICETHREAD_H_INCLUDED
+#define JUCE_TIMESLICETHREAD_H_INCLUDED
+
+class TimeSliceThread;
+
+
+//==============================================================================
+/**
+ Used by the TimeSliceThread class.
+
+ To register your class with a TimeSliceThread, derive from this class and
+ use the TimeSliceThread::addTimeSliceClient() method to add it to the list.
+
+ Make sure you always call TimeSliceThread::removeTimeSliceClient() before
+ deleting your client!
+
+ @see TimeSliceThread
+*/
+class JUCE_API TimeSliceClient
+{
+public:
+ /** Destructor. */
+ virtual ~TimeSliceClient() {}
+
+ /** Called back by a TimeSliceThread.
+
+ When you register this class with it, a TimeSliceThread will repeatedly call
+ this method.
+
+ The implementation of this method should use its time-slice to do something that's
+ quick - never block for longer than absolutely necessary.
+
+ @returns Your method should return the number of milliseconds which it would like to wait before being called
+ again. Returning 0 will make the thread call again as soon as possible (after possibly servicing
+ other busy clients). If you return a value below zero, your client will be removed from the list of clients,
+ and won't be called again. The value you specify isn't a guaranteee, and is only used as a hint by the
+ thread - the actual time before the next callback may be more or less than specified.
+ You can force the TimeSliceThread to wake up and poll again immediately by calling its notify() method.
+ */
+ virtual int useTimeSlice() = 0;
+
+
+private:
+ friend class TimeSliceThread;
+ Time nextCallTime;
+};
+
+
+//==============================================================================
+/**
+ A thread that keeps a list of clients, and calls each one in turn, giving them
+ all a chance to run some sort of short task.
+
+ @see TimeSliceClient, Thread
+*/
+class JUCE_API TimeSliceThread : public Thread
+{
+public:
+ //==============================================================================
+ /**
+ Creates a TimeSliceThread.
+
+ When first created, the thread is not running. Use the startThread()
+ method to start it.
+ */
+ explicit TimeSliceThread (const String& threadName);
+
+ /** Destructor.
+
+ Deleting a Thread object that is running will only give the thread a
+ brief opportunity to stop itself cleanly, so it's recommended that you
+ should always call stopThread() with a decent timeout before deleting,
+ to avoid the thread being forcibly killed (which is a Bad Thing).
+ */
+ ~TimeSliceThread();
+
+ //==============================================================================
+ /** Adds a client to the list.
+
+ The client's callbacks will start after the number of milliseconds specified
+ by millisecondsBeforeStarting (and this may happen before this method has returned).
+ */
+ void addTimeSliceClient (TimeSliceClient* client, int millisecondsBeforeStarting = 0);
+
+ /** Removes a client from the list.
+
+ This method will make sure that all callbacks to the client have completely
+ finished before the method returns.
+ */
+ void removeTimeSliceClient (TimeSliceClient* client);
+
+ /** If the given client is waiting in the queue, it will be moved to the front
+ and given a time-slice as soon as possible.
+ If the specified client has not been added, nothing will happen.
+ */
+ void moveToFrontOfQueue (TimeSliceClient* client);
+
+ /** Returns the number of registered clients. */
+ int getNumClients() const;
+
+ /** Returns one of the registered clients. */
+ TimeSliceClient* getClient (int index) const;
+
+ //==============================================================================
+ #ifndef DOXYGEN
+ void run() override;
+ #endif
+
+ //==============================================================================
+private:
+ CriticalSection callbackLock, listLock;
+ Array <TimeSliceClient*> clients;
+ TimeSliceClient* clientBeingCalled;
+
+ TimeSliceClient* getNextClient (int index) const;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeSliceThread)
+};
+
+
+#endif // JUCE_TIMESLICETHREAD_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_WaitableEvent.h b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_WaitableEvent.h
new file mode 100644
index 0000000..83f6f06
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/threads/juce_WaitableEvent.h
@@ -0,0 +1,118 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_WAITABLEEVENT_H_INCLUDED
+#define JUCE_WAITABLEEVENT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Allows threads to wait for events triggered by other threads.
+
+ A thread can call wait() on a WaitableObject, and this will suspend the
+ calling thread until another thread wakes it up by calling the signal()
+ method.
+*/
+class JUCE_API WaitableEvent
+{
+public:
+ //==============================================================================
+ /** Creates a WaitableEvent object.
+
+ The object is initially in an unsignalled state.
+
+ @param manualReset If this is false, the event will be reset automatically when the wait()
+ method is called. If manualReset is true, then once the event is signalled,
+ the only way to reset it will be by calling the reset() method.
+ */
+ explicit WaitableEvent (bool manualReset = false) noexcept;
+
+ /** Destructor.
+
+ If other threads are waiting on this object when it gets deleted, this
+ can cause nasty errors, so be careful!
+ */
+ ~WaitableEvent() noexcept;
+
+ //==============================================================================
+ /** Suspends the calling thread until the event has been signalled.
+
+ This will wait until the object's signal() method is called by another thread,
+ or until the timeout expires.
+
+ After the event has been signalled, this method will return true and if manualReset
+ was set to false in the WaitableEvent's constructor, then the event will be reset.
+
+ @param timeOutMilliseconds the maximum time to wait, in milliseconds. A negative
+ value will cause it to wait forever.
+
+ @returns true if the object has been signalled, false if the timeout expires first.
+ @see signal, reset
+ */
+ bool wait (int timeOutMilliseconds = -1) const noexcept;
+
+ //==============================================================================
+ /** Wakes up any threads that are currently waiting on this object.
+
+ If signal() is called when nothing is waiting, the next thread to call wait()
+ will return immediately and reset the signal.
+
+ If the WaitableEvent is manual reset, all current and future threads that wait upon this
+ object will be woken, until reset() is explicitly called.
+
+ If the WaitableEvent is automatic reset, and one or more threads is waiting upon the object,
+ then one of them will be woken up. If no threads are currently waiting, then the next thread
+ to call wait() will be woken up. As soon as a thread is woken, the signal is automatically
+ reset.
+
+ @see wait, reset
+ */
+ void signal() const noexcept;
+
+ //==============================================================================
+ /** Resets the event to an unsignalled state.
+ If it's not already signalled, this does nothing.
+ */
+ void reset() const noexcept;
+
+
+private:
+ //==============================================================================
+ #if JUCE_WINDOWS
+ void* handle;
+ #else
+ mutable pthread_cond_t condition;
+ mutable pthread_mutex_t mutex;
+ mutable bool triggered, manualReset;
+ #endif
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WaitableEvent)
+};
+
+
+#endif // JUCE_WAITABLEEVENT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.cpp
new file mode 100644
index 0000000..b22d5e4
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.cpp
@@ -0,0 +1,132 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+static void appendToFile (const File& f, const String& s)
+{
+ if (f.getFullPathName().isNotEmpty())
+ {
+ FileOutputStream out (f);
+
+ if (! out.failedToOpen())
+ out << s << newLine;
+ }
+}
+
+PerformanceCounter::PerformanceCounter (const String& name, int runsPerPrintout, const File& loggingFile)
+ : runsPerPrint (runsPerPrintout), startTime (0), outputFile (loggingFile)
+{
+ stats.name = name;
+ appendToFile (outputFile, "**** Counter for \"" + name + "\" started at: " + Time::getCurrentTime().toString (true, true));
+}
+
+PerformanceCounter::~PerformanceCounter()
+{
+ printStatistics();
+}
+
+PerformanceCounter::Statistics::Statistics() noexcept
+ : averageSeconds(), maximumSeconds(), minimumSeconds(), totalSeconds(), numRuns()
+{
+}
+
+void PerformanceCounter::Statistics::clear() noexcept
+{
+ averageSeconds = maximumSeconds = minimumSeconds = totalSeconds = 0;
+ numRuns = 0;
+}
+
+void PerformanceCounter::Statistics::addResult (double elapsed) noexcept
+{
+ if (numRuns == 0)
+ {
+ maximumSeconds = elapsed;
+ minimumSeconds = elapsed;
+ }
+ else
+ {
+ maximumSeconds = jmax (maximumSeconds, elapsed);
+ minimumSeconds = jmin (minimumSeconds, elapsed);
+ }
+
+ ++numRuns;
+ totalSeconds += elapsed;
+}
+
+static String timeToString (double secs)
+{
+ return String ((int64) (secs * (secs < 0.01 ? 1000000.0 : 1000.0) + 0.5))
+ + (secs < 0.01 ? " microsecs" : " millisecs");
+}
+
+String PerformanceCounter::Statistics::toString() const
+{
+ MemoryOutputStream s;
+
+ s << "Performance count for \"" << name << "\" over " << numRuns << " run(s)" << newLine
+ << "Average = " << timeToString (averageSeconds)
+ << ", minimum = " << timeToString (minimumSeconds)
+ << ", maximum = " << timeToString (maximumSeconds)
+ << ", total = " << timeToString (totalSeconds);
+
+ return s.toString();
+}
+
+void PerformanceCounter::start() noexcept
+{
+ startTime = Time::getHighResolutionTicks();
+}
+
+bool PerformanceCounter::stop()
+{
+ stats.addResult (Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - startTime));
+
+ if (stats.numRuns < runsPerPrint)
+ return false;
+
+ printStatistics();
+ return true;
+}
+
+void PerformanceCounter::printStatistics()
+{
+ const String desc (getStatisticsAndReset().toString());
+
+ Logger::outputDebugString (desc);
+ appendToFile (outputFile, desc);
+}
+
+PerformanceCounter::Statistics PerformanceCounter::getStatisticsAndReset()
+{
+ Statistics s (stats);
+ stats.clear();
+
+ if (s.numRuns > 0)
+ s.averageSeconds = s.totalSeconds / s.numRuns;
+
+ return s;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.h b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.h
new file mode 100644
index 0000000..aac50d2
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_PerformanceCounter.h
@@ -0,0 +1,127 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_PERFORMANCECOUNTER_H_INCLUDED
+#define JUCE_PERFORMANCECOUNTER_H_INCLUDED
+
+
+//==============================================================================
+/** A timer for measuring performance of code and dumping the results to a file.
+
+ e.g. @code
+
+ PerformanceCounter pc ("fish", 50, "/temp/myfishlog.txt");
+
+ for (;;)
+ {
+ pc.start();
+
+ doSomethingFishy();
+
+ pc.stop();
+ }
+ @endcode
+
+ In this example, the time of each period between calling start/stop will be
+ measured and averaged over 50 runs, and the results printed to a file
+ every 50 times round the loop.
+*/
+class JUCE_API PerformanceCounter
+{
+public:
+ //==============================================================================
+ /** Creates a PerformanceCounter object.
+
+ @param counterName the name used when printing out the statistics
+ @param runsPerPrintout the number of start/stop iterations before calling
+ printStatistics()
+ @param loggingFile a file to dump the results to - if this is File::nonexistent,
+ the results are just written to the debugger output
+ */
+ PerformanceCounter (const String& counterName,
+ int runsPerPrintout = 100,
+ const File& loggingFile = File());
+
+ /** Destructor. */
+ ~PerformanceCounter();
+
+ //==============================================================================
+ /** Starts timing.
+ @see stop
+ */
+ void start() noexcept;
+
+ /** Stops timing and prints out the results.
+
+ The number of iterations before doing a printout of the
+ results is set in the constructor.
+
+ @see start
+ */
+ bool stop();
+
+ /** Dumps the current metrics to the debugger output and to a file.
+
+ As well as using Logger::outputDebugString to print the results,
+ this will write then to the file specified in the constructor (if
+ this was valid).
+ */
+ void printStatistics();
+
+ /** Holds the current statistics. */
+ struct Statistics
+ {
+ Statistics() noexcept;
+
+ void clear() noexcept;
+ String toString() const;
+
+ void addResult (double elapsed) noexcept;
+
+ String name;
+ double averageSeconds;
+ double maximumSeconds;
+ double minimumSeconds;
+ double totalSeconds;
+ int64 numRuns;
+ };
+
+ /** Returns a copy of the current stats, and resets the internal counter. */
+ Statistics getStatisticsAndReset();
+
+private:
+ //==============================================================================
+ Statistics stats;
+ int64 runsPerPrint, startTime;
+ File outputFile;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PerformanceCounter)
+};
+
+
+#endif // JUCE_PERFORMANCECOUNTER_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.cpp
new file mode 100644
index 0000000..6fca4fe
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.cpp
@@ -0,0 +1,139 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+RelativeTime::RelativeTime (const double secs) noexcept : numSeconds (secs) {}
+RelativeTime::RelativeTime (const RelativeTime& other) noexcept : numSeconds (other.numSeconds) {}
+RelativeTime::~RelativeTime() noexcept {}
+
+//==============================================================================
+RelativeTime RelativeTime::milliseconds (const int milliseconds) noexcept { return RelativeTime (milliseconds * 0.001); }
+RelativeTime RelativeTime::milliseconds (const int64 milliseconds) noexcept { return RelativeTime (milliseconds * 0.001); }
+RelativeTime RelativeTime::seconds (double s) noexcept { return RelativeTime (s); }
+RelativeTime RelativeTime::minutes (const double numberOfMinutes) noexcept { return RelativeTime (numberOfMinutes * 60.0); }
+RelativeTime RelativeTime::hours (const double numberOfHours) noexcept { return RelativeTime (numberOfHours * (60.0 * 60.0)); }
+RelativeTime RelativeTime::days (const double numberOfDays) noexcept { return RelativeTime (numberOfDays * (60.0 * 60.0 * 24.0)); }
+RelativeTime RelativeTime::weeks (const double numberOfWeeks) noexcept { return RelativeTime (numberOfWeeks * (60.0 * 60.0 * 24.0 * 7.0)); }
+
+//==============================================================================
+int64 RelativeTime::inMilliseconds() const noexcept { return (int64) (numSeconds * 1000.0); }
+double RelativeTime::inMinutes() const noexcept { return numSeconds / 60.0; }
+double RelativeTime::inHours() const noexcept { return numSeconds / (60.0 * 60.0); }
+double RelativeTime::inDays() const noexcept { return numSeconds / (60.0 * 60.0 * 24.0); }
+double RelativeTime::inWeeks() const noexcept { return numSeconds / (60.0 * 60.0 * 24.0 * 7.0); }
+
+//==============================================================================
+RelativeTime& RelativeTime::operator= (const RelativeTime& other) noexcept { numSeconds = other.numSeconds; return *this; }
+
+RelativeTime RelativeTime::operator+= (RelativeTime t) noexcept { numSeconds += t.numSeconds; return *this; }
+RelativeTime RelativeTime::operator-= (RelativeTime t) noexcept { numSeconds -= t.numSeconds; return *this; }
+RelativeTime RelativeTime::operator+= (const double secs) noexcept { numSeconds += secs; return *this; }
+RelativeTime RelativeTime::operator-= (const double secs) noexcept { numSeconds -= secs; return *this; }
+
+RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept { return t1 += t2; }
+RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept { return t1 -= t2; }
+
+bool operator== (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() == t2.inSeconds(); }
+bool operator!= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() != t2.inSeconds(); }
+bool operator> (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() > t2.inSeconds(); }
+bool operator< (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() < t2.inSeconds(); }
+bool operator>= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() >= t2.inSeconds(); }
+bool operator<= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() <= t2.inSeconds(); }
+
+//==============================================================================
+static void translateTimeField (String& result, int n, const char* singular, const char* plural)
+{
+ result << TRANS (n == 1 ? singular : plural)
+ .replace (n == 1 ? "1" : "2", String (n))
+ << ' ';
+}
+
+String RelativeTime::getDescription (const String& returnValueForZeroTime) const
+{
+ if (numSeconds < 0.001 && numSeconds > -0.001)
+ return returnValueForZeroTime;
+
+ String result;
+ result.preallocateBytes (32);
+
+ if (numSeconds < 0)
+ result << '-';
+
+ int fieldsShown = 0;
+ int n = std::abs ((int) inWeeks());
+ if (n > 0)
+ {
+ translateTimeField (result, n, NEEDS_TRANS("1 week"), NEEDS_TRANS("2 weeks"));
+ ++fieldsShown;
+ }
+
+ n = std::abs ((int) inDays()) % 7;
+ if (n > 0)
+ {
+ translateTimeField (result, n, NEEDS_TRANS("1 day"), NEEDS_TRANS("2 days"));
+ ++fieldsShown;
+ }
+
+ if (fieldsShown < 2)
+ {
+ n = std::abs ((int) inHours()) % 24;
+ if (n > 0)
+ {
+ translateTimeField (result, n, NEEDS_TRANS("1 hr"), NEEDS_TRANS("2 hrs"));
+ ++fieldsShown;
+ }
+
+ if (fieldsShown < 2)
+ {
+ n = std::abs ((int) inMinutes()) % 60;
+ if (n > 0)
+ {
+ translateTimeField (result, n, NEEDS_TRANS("1 min"), NEEDS_TRANS("2 mins"));
+ ++fieldsShown;
+ }
+
+ if (fieldsShown < 2)
+ {
+ n = std::abs ((int) inSeconds()) % 60;
+ if (n > 0)
+ {
+ translateTimeField (result, n, NEEDS_TRANS("1 sec"), NEEDS_TRANS("2 secs"));
+ ++fieldsShown;
+ }
+
+ if (fieldsShown == 0)
+ {
+ n = std::abs ((int) inMilliseconds()) % 1000;
+ if (n > 0)
+ result << n << ' ' << TRANS ("ms");
+ }
+ }
+ }
+ }
+
+ return result.trimEnd();
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.h b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.h
new file mode 100644
index 0000000..7e39d21
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_RelativeTime.h
@@ -0,0 +1,184 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_RELATIVETIME_H_INCLUDED
+#define JUCE_RELATIVETIME_H_INCLUDED
+
+
+//==============================================================================
+/** A relative measure of time.
+
+ The time is stored as a number of seconds, at double-precision floating
+ point accuracy, and may be positive or negative.
+
+ If you need an absolute time, (i.e. a date + time), see the Time class.
+*/
+class JUCE_API RelativeTime
+{
+public:
+ //==============================================================================
+ /** Creates a RelativeTime.
+
+ @param seconds the number of seconds, which may be +ve or -ve.
+ @see milliseconds, minutes, hours, days, weeks
+ */
+ explicit RelativeTime (double seconds = 0.0) noexcept;
+
+ /** Copies another relative time. */
+ RelativeTime (const RelativeTime& other) noexcept;
+
+ /** Copies another relative time. */
+ RelativeTime& operator= (const RelativeTime& other) noexcept;
+
+ /** Destructor. */
+ ~RelativeTime() noexcept;
+
+ //==============================================================================
+ /** Creates a new RelativeTime object representing a number of milliseconds.
+ @see seconds, minutes, hours, days, weeks
+ */
+ static RelativeTime milliseconds (int milliseconds) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of milliseconds.
+ @see seconds, minutes, hours, days, weeks
+ */
+ static RelativeTime milliseconds (int64 milliseconds) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of seconds.
+ @see milliseconds, minutes, hours, days, weeks
+ */
+ static RelativeTime seconds (double seconds) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of minutes.
+ @see milliseconds, hours, days, weeks
+ */
+ static RelativeTime minutes (double numberOfMinutes) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of hours.
+ @see milliseconds, minutes, days, weeks
+ */
+ static RelativeTime hours (double numberOfHours) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of days.
+ @see milliseconds, minutes, hours, weeks
+ */
+ static RelativeTime days (double numberOfDays) noexcept;
+
+ /** Creates a new RelativeTime object representing a number of weeks.
+ @see milliseconds, minutes, hours, days
+ */
+ static RelativeTime weeks (double numberOfWeeks) noexcept;
+
+ //==============================================================================
+ /** Returns the number of milliseconds this time represents.
+ @see milliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks
+ */
+ int64 inMilliseconds() const noexcept;
+
+ /** Returns the number of seconds this time represents.
+ @see inMilliseconds, inMinutes, inHours, inDays, inWeeks
+ */
+ double inSeconds() const noexcept { return numSeconds; }
+
+ /** Returns the number of minutes this time represents.
+ @see inMilliseconds, inSeconds, inHours, inDays, inWeeks
+ */
+ double inMinutes() const noexcept;
+
+ /** Returns the number of hours this time represents.
+ @see inMilliseconds, inSeconds, inMinutes, inDays, inWeeks
+ */
+ double inHours() const noexcept;
+
+ /** Returns the number of days this time represents.
+ @see inMilliseconds, inSeconds, inMinutes, inHours, inWeeks
+ */
+ double inDays() const noexcept;
+
+ /** Returns the number of weeks this time represents.
+ @see inMilliseconds, inSeconds, inMinutes, inHours, inDays
+ */
+ double inWeeks() const noexcept;
+
+ /** Returns a readable textual description of the time.
+
+ The exact format of the string returned will depend on
+ the magnitude of the time - e.g.
+
+ "1 min 4 secs", "1 hr 45 mins", "2 weeks 5 days", "140 ms"
+
+ so that only the two most significant units are printed.
+
+ The returnValueForZeroTime value is the result that is returned if the
+ length is zero. Depending on your application you might want to use this
+ to return something more relevant like "empty" or "0 secs", etc.
+
+ @see inMilliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks
+ */
+ String getDescription (const String& returnValueForZeroTime = "0") const;
+
+
+ //==============================================================================
+ /** Adds another RelativeTime to this one. */
+ RelativeTime operator+= (RelativeTime timeToAdd) noexcept;
+ /** Subtracts another RelativeTime from this one. */
+ RelativeTime operator-= (RelativeTime timeToSubtract) noexcept;
+
+ /** Adds a number of seconds to this time. */
+ RelativeTime operator+= (double secondsToAdd) noexcept;
+ /** Subtracts a number of seconds from this time. */
+ RelativeTime operator-= (double secondsToSubtract) noexcept;
+
+private:
+ //==============================================================================
+ double numSeconds;
+};
+
+//==============================================================================
+/** Compares two RelativeTimes. */
+bool operator== (RelativeTime t1, RelativeTime t2) noexcept;
+/** Compares two RelativeTimes. */
+bool operator!= (RelativeTime t1, RelativeTime t2) noexcept;
+/** Compares two RelativeTimes. */
+bool operator> (RelativeTime t1, RelativeTime t2) noexcept;
+/** Compares two RelativeTimes. */
+bool operator< (RelativeTime t1, RelativeTime t2) noexcept;
+/** Compares two RelativeTimes. */
+bool operator>= (RelativeTime t1, RelativeTime t2) noexcept;
+/** Compares two RelativeTimes. */
+bool operator<= (RelativeTime t1, RelativeTime t2) noexcept;
+
+//==============================================================================
+/** Adds two RelativeTimes together. */
+RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept;
+/** Subtracts two RelativeTimes. */
+RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept;
+
+
+
+#endif // JUCE_RELATIVETIME_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.cpp
new file mode 100644
index 0000000..fabcfde
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.cpp
@@ -0,0 +1,469 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+namespace TimeHelpers
+{
+ static struct tm millisToLocal (const int64 millis) noexcept
+ {
+ struct tm result;
+ const int64 seconds = millis / 1000;
+
+ if (seconds < 86400LL || seconds >= 2145916800LL)
+ {
+ // use extended maths for dates beyond 1970 to 2037..
+ const int timeZoneAdjustment = 31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000);
+ const int64 jdm = seconds + timeZoneAdjustment + 210866803200LL;
+
+ const int days = (int) (jdm / 86400LL);
+ const int a = 32044 + days;
+ const int b = (4 * a + 3) / 146097;
+ const int c = a - (b * 146097) / 4;
+ const int d = (4 * c + 3) / 1461;
+ const int e = c - (d * 1461) / 4;
+ const int m = (5 * e + 2) / 153;
+
+ result.tm_mday = e - (153 * m + 2) / 5 + 1;
+ result.tm_mon = m + 2 - 12 * (m / 10);
+ result.tm_year = b * 100 + d - 6700 + (m / 10);
+ result.tm_wday = (days + 1) % 7;
+ result.tm_yday = -1;
+
+ int t = (int) (jdm % 86400LL);
+ result.tm_hour = t / 3600;
+ t %= 3600;
+ result.tm_min = t / 60;
+ result.tm_sec = t % 60;
+ result.tm_isdst = -1;
+ }
+ else
+ {
+ time_t now = static_cast <time_t> (seconds);
+
+ #if JUCE_WINDOWS
+ #ifdef _INC_TIME_INL
+ if (now >= 0 && now <= 0x793406fff)
+ localtime_s (&result, &now);
+ else
+ zerostruct (result);
+ #else
+ result = *localtime (&now);
+ #endif
+ #else
+
+ localtime_r (&now, &result); // more thread-safe
+ #endif
+ }
+
+ return result;
+ }
+
+ static int extendedModulo (const int64 value, const int modulo) noexcept
+ {
+ return (int) (value >= 0 ? (value % modulo)
+ : (value - ((value / modulo) + 1) * modulo));
+ }
+
+ static inline String formatString (const String& format, const struct tm* const tm)
+ {
+ #if JUCE_ANDROID
+ typedef CharPointer_UTF8 StringType;
+ #elif JUCE_WINDOWS
+ typedef CharPointer_UTF16 StringType;
+ #else
+ typedef CharPointer_UTF32 StringType;
+ #endif
+
+ for (size_t bufferSize = 256; ; bufferSize += 256)
+ {
+ HeapBlock<StringType::CharType> buffer (bufferSize);
+
+ #if JUCE_ANDROID
+ const size_t numChars = strftime (buffer, bufferSize - 1, format.toUTF8(), tm);
+ #elif JUCE_WINDOWS
+ const size_t numChars = wcsftime (buffer, bufferSize - 1, format.toWideCharPointer(), tm);
+ #else
+ const size_t numChars = wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm);
+ #endif
+
+ if (numChars > 0 || format.isEmpty())
+ return String (StringType (buffer),
+ StringType (buffer) + (int) numChars);
+ }
+ }
+
+ static uint32 lastMSCounterValue = 0;
+}
+
+//==============================================================================
+Time::Time() noexcept
+ : millisSinceEpoch (0)
+{
+}
+
+Time::Time (const Time& other) noexcept
+ : millisSinceEpoch (other.millisSinceEpoch)
+{
+}
+
+Time::Time (const int64 ms) noexcept
+ : millisSinceEpoch (ms)
+{
+}
+
+Time::Time (const int year,
+ const int month,
+ const int day,
+ const int hours,
+ const int minutes,
+ const int seconds,
+ const int milliseconds,
+ const bool useLocalTime) noexcept
+{
+ jassert (year > 100); // year must be a 4-digit version
+
+ if (year < 1971 || year >= 2038 || ! useLocalTime)
+ {
+ // use extended maths for dates beyond 1970 to 2037..
+ const int timeZoneAdjustment = useLocalTime ? (31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000))
+ : 0;
+ const int a = (13 - month) / 12;
+ const int y = year + 4800 - a;
+ const int jd = day + (153 * (month + 12 * a - 2) + 2) / 5
+ + (y * 365) + (y / 4) - (y / 100) + (y / 400)
+ - 32045;
+
+ const int64 s = ((int64) jd) * 86400LL - 210866803200LL;
+
+ millisSinceEpoch = 1000 * (s + (hours * 3600 + minutes * 60 + seconds - timeZoneAdjustment))
+ + milliseconds;
+ }
+ else
+ {
+ struct tm t;
+ t.tm_year = year - 1900;
+ t.tm_mon = month;
+ t.tm_mday = day;
+ t.tm_hour = hours;
+ t.tm_min = minutes;
+ t.tm_sec = seconds;
+ t.tm_isdst = -1;
+
+ millisSinceEpoch = 1000 * (int64) mktime (&t);
+
+ if (millisSinceEpoch < 0)
+ millisSinceEpoch = 0;
+ else
+ millisSinceEpoch += milliseconds;
+ }
+}
+
+Time::~Time() noexcept
+{
+}
+
+Time& Time::operator= (const Time& other) noexcept
+{
+ millisSinceEpoch = other.millisSinceEpoch;
+ return *this;
+}
+
+//==============================================================================
+int64 Time::currentTimeMillis() noexcept
+{
+ #if JUCE_WINDOWS
+ struct _timeb t;
+ #ifdef _INC_TIME_INL
+ _ftime_s (&t);
+ #else
+ _ftime (&t);
+ #endif
+ return ((int64) t.time) * 1000 + t.millitm;
+ #else
+ struct timeval tv;
+ gettimeofday (&tv, nullptr);
+ return ((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+ #endif
+}
+
+Time JUCE_CALLTYPE Time::getCurrentTime() noexcept
+{
+ return Time (currentTimeMillis());
+}
+
+//==============================================================================
+uint32 juce_millisecondsSinceStartup() noexcept;
+
+uint32 Time::getMillisecondCounter() noexcept
+{
+ const uint32 now = juce_millisecondsSinceStartup();
+
+ if (now < TimeHelpers::lastMSCounterValue)
+ {
+ // in multi-threaded apps this might be called concurrently, so
+ // make sure that our last counter value only increases and doesn't
+ // go backwards..
+ if (now < TimeHelpers::lastMSCounterValue - 1000)
+ TimeHelpers::lastMSCounterValue = now;
+ }
+ else
+ {
+ TimeHelpers::lastMSCounterValue = now;
+ }
+
+ return now;
+}
+
+uint32 Time::getApproximateMillisecondCounter() noexcept
+{
+ if (TimeHelpers::lastMSCounterValue == 0)
+ getMillisecondCounter();
+
+ return TimeHelpers::lastMSCounterValue;
+}
+
+void Time::waitForMillisecondCounter (const uint32 targetTime) noexcept
+{
+ for (;;)
+ {
+ const uint32 now = getMillisecondCounter();
+
+ if (now >= targetTime)
+ break;
+
+ const int toWait = (int) (targetTime - now);
+
+ if (toWait > 2)
+ {
+ Thread::sleep (jmin (20, toWait >> 1));
+ }
+ else
+ {
+ // xxx should consider using mutex_pause on the mac as it apparently
+ // makes it seem less like a spinlock and avoids lowering the thread pri.
+ for (int i = 10; --i >= 0;)
+ Thread::yield();
+ }
+ }
+}
+
+//==============================================================================
+double Time::highResolutionTicksToSeconds (const int64 ticks) noexcept
+{
+ return ticks / (double) getHighResolutionTicksPerSecond();
+}
+
+int64 Time::secondsToHighResolutionTicks (const double seconds) noexcept
+{
+ return (int64) (seconds * (double) getHighResolutionTicksPerSecond());
+}
+
+//==============================================================================
+String Time::toString (const bool includeDate,
+ const bool includeTime,
+ const bool includeSeconds,
+ const bool use24HourClock) const noexcept
+{
+ String result;
+
+ if (includeDate)
+ {
+ result << getDayOfMonth() << ' '
+ << getMonthName (true) << ' '
+ << getYear();
+
+ if (includeTime)
+ result << ' ';
+ }
+
+ if (includeTime)
+ {
+ const int mins = getMinutes();
+
+ result << (use24HourClock ? getHours() : getHoursInAmPmFormat())
+ << (mins < 10 ? ":0" : ":") << mins;
+
+ if (includeSeconds)
+ {
+ const int secs = getSeconds();
+ result << (secs < 10 ? ":0" : ":") << secs;
+ }
+
+ if (! use24HourClock)
+ result << (isAfternoon() ? "pm" : "am");
+ }
+
+ return result.trimEnd();
+}
+
+String Time::formatted (const String& format) const
+{
+ struct tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
+ return TimeHelpers::formatString (format, &t);
+}
+
+//==============================================================================
+int Time::getYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; }
+int Time::getMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; }
+int Time::getDayOfYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; }
+int Time::getDayOfMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mday; }
+int Time::getDayOfWeek() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; }
+int Time::getHours() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; }
+int Time::getMinutes() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; }
+int Time::getSeconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); }
+int Time::getMilliseconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch, 1000); }
+
+int Time::getHoursInAmPmFormat() const noexcept
+{
+ const int hours = getHours();
+
+ if (hours == 0) return 12;
+ if (hours <= 12) return hours;
+
+ return hours - 12;
+}
+
+bool Time::isAfternoon() const noexcept
+{
+ return getHours() >= 12;
+}
+
+bool Time::isDaylightSavingTime() const noexcept
+{
+ return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0;
+}
+
+String Time::getTimeZone() const noexcept
+{
+ String zone[2];
+
+ #if JUCE_WINDOWS
+ _tzset();
+
+ #ifdef _INC_TIME_INL
+ for (int i = 0; i < 2; ++i)
+ {
+ char name[128] = { 0 };
+ size_t length;
+ _get_tzname (&length, name, 127, i);
+ zone[i] = name;
+ }
+ #else
+ const char** const zonePtr = (const char**) _tzname;
+ zone[0] = zonePtr[0];
+ zone[1] = zonePtr[1];
+ #endif
+ #else
+ tzset();
+ const char** const zonePtr = (const char**) tzname;
+ zone[0] = zonePtr[0];
+ zone[1] = zonePtr[1];
+ #endif
+
+ if (isDaylightSavingTime())
+ {
+ zone[0] = zone[1];
+
+ if (zone[0].length() > 3
+ && zone[0].containsIgnoreCase ("daylight")
+ && zone[0].contains ("GMT"))
+ zone[0] = "BST";
+ }
+
+ return zone[0].substring (0, 3);
+}
+
+String Time::getMonthName (const bool threeLetterVersion) const
+{
+ return getMonthName (getMonth(), threeLetterVersion);
+}
+
+String Time::getWeekdayName (const bool threeLetterVersion) const
+{
+ return getWeekdayName (getDayOfWeek(), threeLetterVersion);
+}
+
+static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
+
+String Time::getMonthName (int monthNumber, const bool threeLetterVersion)
+{
+ monthNumber %= 12;
+
+ return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
+ : longMonthNames [monthNumber]);
+}
+
+String Time::getWeekdayName (int day, const bool threeLetterVersion)
+{
+ static const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ static const char* const longDayNames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+
+ day %= 7;
+
+ return TRANS (threeLetterVersion ? shortDayNames [day]
+ : longDayNames [day]);
+}
+
+//==============================================================================
+Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; }
+Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; }
+
+Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; }
+Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; }
+Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; }
+const RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
+
+bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); }
+bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); }
+bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); }
+bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); }
+bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); }
+bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); }
+
+static int getMonthNumberForCompileDate (const String& m) noexcept
+{
+ for (int i = 0; i < 12; ++i)
+ if (m.equalsIgnoreCase (shortMonthNames[i]))
+ return i;
+
+ // If you hit this because your compiler has a non-standard __DATE__ format,
+ // let me know so we can add support for it!
+ jassertfalse;
+ return 0;
+}
+
+Time Time::getCompilationDate()
+{
+ StringArray dateTokens;
+ dateTokens.addTokens (__DATE__, true);
+ dateTokens.removeEmptyStrings (true);
+
+ return Time (dateTokens[2].getIntValue(),
+ getMonthNumberForCompileDate (dateTokens[0]),
+ dateTokens[1].getIntValue(), 12, 0);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.h b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.h
new file mode 100644
index 0000000..4a35e08
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/time/juce_Time.h
@@ -0,0 +1,404 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_TIME_H_INCLUDED
+#define JUCE_TIME_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Holds an absolute date and time.
+
+ Internally, the time is stored at millisecond precision.
+
+ @see RelativeTime
+*/
+class JUCE_API Time
+{
+public:
+ //==============================================================================
+ /** Creates a Time object.
+
+ This default constructor creates a time of 1st January 1970, (which is
+ represented internally as 0ms).
+
+ To create a time object representing the current time, use getCurrentTime().
+
+ @see getCurrentTime
+ */
+ Time() noexcept;
+
+ /** Creates a time based on a number of milliseconds.
+
+ The internal millisecond count is set to 0 (1st January 1970). To create a
+ time object set to the current time, use getCurrentTime().
+
+ @param millisecondsSinceEpoch the number of milliseconds since the unix
+ 'epoch' (midnight Jan 1st 1970).
+ @see getCurrentTime, currentTimeMillis
+ */
+ explicit Time (int64 millisecondsSinceEpoch) noexcept;
+
+ /** Creates a time from a set of date components.
+
+ The timezone is assumed to be whatever the system is using as its locale.
+
+ @param year the year, in 4-digit format, e.g. 2004
+ @param month the month, in the range 0 to 11
+ @param day the day of the month, in the range 1 to 31
+ @param hours hours in 24-hour clock format, 0 to 23
+ @param minutes minutes 0 to 59
+ @param seconds seconds 0 to 59
+ @param milliseconds milliseconds 0 to 999
+ @param useLocalTime if true, encode using the current machine's local time; if
+ false, it will always work in GMT.
+ */
+ Time (int year,
+ int month,
+ int day,
+ int hours,
+ int minutes,
+ int seconds = 0,
+ int milliseconds = 0,
+ bool useLocalTime = true) noexcept;
+
+ /** Creates a copy of another Time object. */
+ Time (const Time& other) noexcept;
+
+ /** Destructor. */
+ ~Time() noexcept;
+
+ /** Copies this time from another one. */
+ Time& operator= (const Time& other) noexcept;
+
+ //==============================================================================
+ /** Returns a Time object that is set to the current system time.
+
+ @see currentTimeMillis
+ */
+ static Time JUCE_CALLTYPE getCurrentTime() noexcept;
+
+ /** Returns the time as a number of milliseconds.
+
+ @returns the number of milliseconds this Time object represents, since
+ midnight jan 1st 1970.
+ @see getMilliseconds
+ */
+ int64 toMilliseconds() const noexcept { return millisSinceEpoch; }
+
+ /** Returns the year.
+
+ A 4-digit format is used, e.g. 2004.
+ */
+ int getYear() const noexcept;
+
+ /** Returns the number of the month.
+
+ The value returned is in the range 0 to 11.
+ @see getMonthName
+ */
+ int getMonth() const noexcept;
+
+ /** Returns the name of the month.
+
+ @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false
+ it'll return the long form, e.g. "January"
+ @see getMonth
+ */
+ String getMonthName (bool threeLetterVersion) const;
+
+ /** Returns the day of the month.
+ The value returned is in the range 1 to 31.
+ */
+ int getDayOfMonth() const noexcept;
+
+ /** Returns the number of the day of the week.
+ The value returned is in the range 0 to 6 (0 = sunday, 1 = monday, etc).
+ */
+ int getDayOfWeek() const noexcept;
+
+ /** Returns the number of the day of the year.
+ The value returned is in the range 0 to 365.
+ */
+ int getDayOfYear() const noexcept;
+
+ /** Returns the name of the weekday.
+
+ @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if
+ false, it'll return the full version, e.g. "Tuesday".
+ */
+ String getWeekdayName (bool threeLetterVersion) const;
+
+ /** Returns the number of hours since midnight.
+
+ This is in 24-hour clock format, in the range 0 to 23.
+
+ @see getHoursInAmPmFormat, isAfternoon
+ */
+ int getHours() const noexcept;
+
+ /** Returns true if the time is in the afternoon.
+
+ So it returns true for "PM", false for "AM".
+
+ @see getHoursInAmPmFormat, getHours
+ */
+ bool isAfternoon() const noexcept;
+
+ /** Returns the hours in 12-hour clock format.
+
+ This will return a value 1 to 12 - use isAfternoon() to find out
+ whether this is in the afternoon or morning.
+
+ @see getHours, isAfternoon
+ */
+ int getHoursInAmPmFormat() const noexcept;
+
+ /** Returns the number of minutes, 0 to 59. */
+ int getMinutes() const noexcept;
+
+ /** Returns the number of seconds, 0 to 59. */
+ int getSeconds() const noexcept;
+
+ /** Returns the number of milliseconds, 0 to 999.
+
+ Unlike toMilliseconds(), this just returns the position within the
+ current second rather than the total number since the epoch.
+
+ @see toMilliseconds
+ */
+ int getMilliseconds() const noexcept;
+
+ /** Returns true if the local timezone uses a daylight saving correction. */
+ bool isDaylightSavingTime() const noexcept;
+
+ /** Returns a 3-character string to indicate the local timezone. */
+ String getTimeZone() const noexcept;
+
+ //==============================================================================
+ /** Quick way of getting a string version of a date and time.
+
+ For a more powerful way of formatting the date and time, see the formatted() method.
+
+ @param includeDate whether to include the date in the string
+ @param includeTime whether to include the time in the string
+ @param includeSeconds if the time is being included, this provides an option not to include
+ the seconds in it
+ @param use24HourClock if the time is being included, sets whether to use am/pm or 24
+ hour notation.
+ @see formatted
+ */
+ String toString (bool includeDate,
+ bool includeTime,
+ bool includeSeconds = true,
+ bool use24HourClock = false) const noexcept;
+
+ /** Converts this date/time to a string with a user-defined format.
+
+ This uses the C strftime() function to format this time as a string. To save you
+ looking it up, these are the escape codes that strftime uses (other codes might
+ work on some platforms and not others, but these are the common ones):
+
+ %a is replaced by the locale's abbreviated weekday name.
+ %A is replaced by the locale's full weekday name.
+ %b is replaced by the locale's abbreviated month name.
+ %B is replaced by the locale's full month name.
+ %c is replaced by the locale's appropriate date and time representation.
+ %d is replaced by the day of the month as a decimal number [01,31].
+ %H is replaced by the hour (24-hour clock) as a decimal number [00,23].
+ %I is replaced by the hour (12-hour clock) as a decimal number [01,12].
+ %j is replaced by the day of the year as a decimal number [001,366].
+ %m is replaced by the month as a decimal number [01,12].
+ %M is replaced by the minute as a decimal number [00,59].
+ %p is replaced by the locale's equivalent of either a.m. or p.m.
+ %S is replaced by the second as a decimal number [00,61].
+ %U is replaced by the week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
+ %w is replaced by the weekday as a decimal number [0,6], with 0 representing Sunday.
+ %W is replaced by the week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0.
+ %x is replaced by the locale's appropriate date representation.
+ %X is replaced by the locale's appropriate time representation.
+ %y is replaced by the year without century as a decimal number [00,99].
+ %Y is replaced by the year with century as a decimal number.
+ %Z is replaced by the timezone name or abbreviation, or by no bytes if no timezone information exists.
+ %% is replaced by %.
+
+ @see toString
+ */
+ String formatted (const String& format) const;
+
+ //==============================================================================
+ /** Adds a RelativeTime to this time. */
+ Time& operator+= (RelativeTime delta) noexcept;
+ /** Subtracts a RelativeTime from this time. */
+ Time& operator-= (RelativeTime delta) noexcept;
+
+ //==============================================================================
+ /** Tries to set the computer's clock.
+
+ @returns true if this succeeds, although depending on the system, the
+ application might not have sufficient privileges to do this.
+ */
+ bool setSystemTimeToThisTime() const;
+
+ //==============================================================================
+ /** Returns the name of a day of the week.
+
+ @param dayNumber the day, 0 to 6 (0 = sunday, 1 = monday, etc)
+ @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if
+ false, it'll return the full version, e.g. "Tuesday".
+ */
+ static String getWeekdayName (int dayNumber, bool threeLetterVersion);
+
+ /** Returns the name of one of the months.
+
+ @param monthNumber the month, 0 to 11
+ @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false
+ it'll return the long form, e.g. "January"
+ */
+ static String getMonthName (int monthNumber, bool threeLetterVersion);
+
+ //==============================================================================
+ // Static methods for getting system timers directly..
+
+ /** Returns the current system time.
+
+ Returns the number of milliseconds since midnight jan 1st 1970.
+
+ Should be accurate to within a few millisecs, depending on platform,
+ hardware, etc.
+ */
+ static int64 currentTimeMillis() noexcept;
+
+ /** Returns the number of millisecs since a fixed event (usually system startup).
+
+ This returns a monotonically increasing value which it unaffected by changes to the
+ system clock. It should be accurate to within a few millisecs, depending on platform,
+ hardware, etc.
+
+ Being a 32-bit return value, it will of course wrap back to 0 after 2^32 seconds of
+ uptime, so be careful to take that into account. If you need a 64-bit time, you can
+ use currentTimeMillis() instead.
+
+ @see getApproximateMillisecondCounter
+ */
+ static uint32 getMillisecondCounter() noexcept;
+
+ /** Returns the number of millisecs since a fixed event (usually system startup).
+
+ This has the same function as getMillisecondCounter(), but returns a more accurate
+ value, using a higher-resolution timer if one is available.
+
+ @see getMillisecondCounter
+ */
+ static double getMillisecondCounterHiRes() noexcept;
+
+ /** Waits until the getMillisecondCounter() reaches a given value.
+
+ This will make the thread sleep as efficiently as it can while it's waiting.
+ */
+ static void waitForMillisecondCounter (uint32 targetTime) noexcept;
+
+ /** Less-accurate but faster version of getMillisecondCounter().
+
+ This will return the last value that getMillisecondCounter() returned, so doesn't
+ need to make a system call, but is less accurate - it shouldn't be more than
+ 100ms away from the correct time, though, so is still accurate enough for a
+ lot of purposes.
+
+ @see getMillisecondCounter
+ */
+ static uint32 getApproximateMillisecondCounter() noexcept;
+
+ //==============================================================================
+ // High-resolution timers..
+
+ /** Returns the current high-resolution counter's tick-count.
+
+ This is a similar idea to getMillisecondCounter(), but with a higher
+ resolution.
+
+ @see getHighResolutionTicksPerSecond, highResolutionTicksToSeconds,
+ secondsToHighResolutionTicks
+ */
+ static int64 getHighResolutionTicks() noexcept;
+
+ /** Returns the resolution of the high-resolution counter in ticks per second.
+
+ @see getHighResolutionTicks, highResolutionTicksToSeconds,
+ secondsToHighResolutionTicks
+ */
+ static int64 getHighResolutionTicksPerSecond() noexcept;
+
+ /** Converts a number of high-resolution ticks into seconds.
+
+ @see getHighResolutionTicks, getHighResolutionTicksPerSecond,
+ secondsToHighResolutionTicks
+ */
+ static double highResolutionTicksToSeconds (int64 ticks) noexcept;
+
+ /** Converts a number seconds into high-resolution ticks.
+
+ @see getHighResolutionTicks, getHighResolutionTicksPerSecond,
+ highResolutionTicksToSeconds
+ */
+ static int64 secondsToHighResolutionTicks (double seconds) noexcept;
+
+ /** Returns a Time based on the value of the __DATE__ macro when this module was compiled */
+ static Time getCompilationDate();
+
+private:
+ //==============================================================================
+ int64 millisSinceEpoch;
+};
+
+//==============================================================================
+/** Adds a RelativeTime to a Time. */
+JUCE_API Time operator+ (Time time, RelativeTime delta) noexcept;
+/** Adds a RelativeTime to a Time. */
+JUCE_API Time operator+ (RelativeTime delta, Time time) noexcept;
+
+/** Subtracts a RelativeTime from a Time. */
+JUCE_API Time operator- (Time time, RelativeTime delta) noexcept;
+/** Returns the relative time difference between two times. */
+JUCE_API const RelativeTime operator- (Time time1, Time time2) noexcept;
+
+/** Compares two Time objects. */
+JUCE_API bool operator== (Time time1, Time time2) noexcept;
+/** Compares two Time objects. */
+JUCE_API bool operator!= (Time time1, Time time2) noexcept;
+/** Compares two Time objects. */
+JUCE_API bool operator< (Time time1, Time time2) noexcept;
+/** Compares two Time objects. */
+JUCE_API bool operator<= (Time time1, Time time2) noexcept;
+/** Compares two Time objects. */
+JUCE_API bool operator> (Time time1, Time time2) noexcept;
+/** Compares two Time objects. */
+JUCE_API bool operator>= (Time time1, Time time2) noexcept;
+
+
+#endif // JUCE_TIME_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.cpp
new file mode 100644
index 0000000..f5a60c1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.cpp
@@ -0,0 +1,260 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+UnitTest::UnitTest (const String& nm)
+ : name (nm), runner (nullptr)
+{
+ getAllTests().add (this);
+}
+
+UnitTest::~UnitTest()
+{
+ getAllTests().removeFirstMatchingValue (this);
+}
+
+Array<UnitTest*>& UnitTest::getAllTests()
+{
+ static Array<UnitTest*> tests;
+ return tests;
+}
+
+void UnitTest::initialise() {}
+void UnitTest::shutdown() {}
+
+void UnitTest::performTest (UnitTestRunner* const newRunner)
+{
+ jassert (newRunner != nullptr);
+ runner = newRunner;
+
+ initialise();
+ runTest();
+ shutdown();
+}
+
+void UnitTest::logMessage (const String& message)
+{
+ // This method's only valid while the test is being run!
+ jassert (runner != nullptr);
+
+ runner->logMessage (message);
+}
+
+void UnitTest::beginTest (const String& testName)
+{
+ // This method's only valid while the test is being run!
+ jassert (runner != nullptr);
+
+ runner->beginNewTest (this, testName);
+}
+
+void UnitTest::expect (const bool result, const String& failureMessage)
+{
+ // This method's only valid while the test is being run!
+ jassert (runner != nullptr);
+
+ if (result)
+ runner->addPass();
+ else
+ runner->addFail (failureMessage);
+}
+
+Random UnitTest::getRandom() const
+{
+ // This method's only valid while the test is being run!
+ jassert (runner != nullptr);
+
+ return runner->randomForTest;
+}
+
+//==============================================================================
+UnitTestRunner::UnitTestRunner()
+ : currentTest (nullptr),
+ assertOnFailure (true),
+ logPasses (false)
+{
+}
+
+UnitTestRunner::~UnitTestRunner()
+{
+}
+
+void UnitTestRunner::setAssertOnFailure (bool shouldAssert) noexcept
+{
+ assertOnFailure = shouldAssert;
+}
+
+void UnitTestRunner::setPassesAreLogged (bool shouldDisplayPasses) noexcept
+{
+ logPasses = shouldDisplayPasses;
+}
+
+int UnitTestRunner::getNumResults() const noexcept
+{
+ return results.size();
+}
+
+const UnitTestRunner::TestResult* UnitTestRunner::getResult (int index) const noexcept
+{
+ return results [index];
+}
+
+void UnitTestRunner::resultsUpdated()
+{
+}
+
+void UnitTestRunner::runTests (const Array<UnitTest*>& tests, int64 randomSeed)
+{
+ results.clear();
+ resultsUpdated();
+
+ if (randomSeed == 0)
+ randomSeed = Random().nextInt (0x7ffffff);
+
+ randomForTest = Random (randomSeed);
+ logMessage ("Random seed: 0x" + String::toHexString (randomSeed));
+
+ for (int i = 0; i < tests.size(); ++i)
+ {
+ if (shouldAbortTests())
+ break;
+
+ try
+ {
+ tests.getUnchecked(i)->performTest (this);
+ }
+ catch (...)
+ {
+ addFail ("An unhandled exception was thrown!");
+ }
+ }
+
+ endTest();
+}
+
+void UnitTestRunner::runAllTests (int64 randomSeed)
+{
+ runTests (UnitTest::getAllTests(), randomSeed);
+}
+
+void UnitTestRunner::logMessage (const String& message)
+{
+ Logger::writeToLog (message);
+}
+
+bool UnitTestRunner::shouldAbortTests()
+{
+ return false;
+}
+
+void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory)
+{
+ endTest();
+ currentTest = test;
+
+ TestResult* const r = new TestResult();
+ results.add (r);
+ r->unitTestName = test->getName();
+ r->subcategoryName = subCategory;
+ r->passes = 0;
+ r->failures = 0;
+
+ logMessage ("-----------------------------------------------------------------");
+ logMessage ("Starting test: " + r->unitTestName + " / " + subCategory + "...");
+
+ resultsUpdated();
+}
+
+void UnitTestRunner::endTest()
+{
+ if (results.size() > 0)
+ {
+ TestResult* const r = results.getLast();
+
+ if (r->failures > 0)
+ {
+ String m ("FAILED!! ");
+ m << r->failures << (r->failures == 1 ? " test" : " tests")
+ << " failed, out of a total of " << (r->passes + r->failures);
+
+ logMessage (String::empty);
+ logMessage (m);
+ logMessage (String::empty);
+ }
+ else
+ {
+ logMessage ("All tests completed successfully");
+ }
+ }
+}
+
+void UnitTestRunner::addPass()
+{
+ {
+ const ScopedLock sl (results.getLock());
+
+ TestResult* const r = results.getLast();
+ jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
+
+ r->passes++;
+
+ if (logPasses)
+ {
+ String message ("Test ");
+ message << (r->failures + r->passes) << " passed";
+ logMessage (message);
+ }
+ }
+
+ resultsUpdated();
+}
+
+void UnitTestRunner::addFail (const String& failureMessage)
+{
+ {
+ const ScopedLock sl (results.getLock());
+
+ TestResult* const r = results.getLast();
+ jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
+
+ r->failures++;
+
+ String message ("!!! Test ");
+ message << (r->failures + r->passes) << " failed";
+
+ if (failureMessage.isNotEmpty())
+ message << ": " << failureMessage;
+
+ r->messages.add (message);
+
+ logMessage (message);
+ }
+
+ resultsUpdated();
+
+ if (assertOnFailure) { jassertfalse; }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.h b/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.h
new file mode 100644
index 0000000..f5908c1
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/unit_tests/juce_UnitTest.h
@@ -0,0 +1,311 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_UNITTEST_H_INCLUDED
+#define JUCE_UNITTEST_H_INCLUDED
+
+class UnitTestRunner;
+
+
+//==============================================================================
+/**
+ This is a base class for classes that perform a unit test.
+
+ To write a test using this class, your code should look something like this:
+
+ @code
+ class MyTest : public UnitTest
+ {
+ public:
+ MyTest() : UnitTest ("Foobar testing") {}
+
+ void runTest()
+ {
+ beginTest ("Part 1");
+
+ expect (myFoobar.doesSomething());
+ expect (myFoobar.doesSomethingElse());
+
+ beginTest ("Part 2");
+
+ expect (myOtherFoobar.doesSomething());
+ expect (myOtherFoobar.doesSomethingElse());
+
+ ...etc..
+ }
+ };
+
+ // Creating a static instance will automatically add the instance to the array
+ // returned by UnitTest::getAllTests(), so the test will be included when you call
+ // UnitTestRunner::runAllTests()
+ static MyTest test;
+ @endcode
+
+ To run a test, use the UnitTestRunner class.
+
+ @see UnitTestRunner
+*/
+class JUCE_API UnitTest
+{
+public:
+ //==============================================================================
+ /** Creates a test with the given name. */
+ explicit UnitTest (const String& name);
+
+ /** Destructor. */
+ virtual ~UnitTest();
+
+ /** Returns the name of the test. */
+ const String& getName() const noexcept { return name; }
+
+ /** Runs the test, using the specified UnitTestRunner.
+ You shouldn't need to call this method directly - use
+ UnitTestRunner::runTests() instead.
+ */
+ void performTest (UnitTestRunner* runner);
+
+ /** Returns the set of all UnitTest objects that currently exist. */
+ static Array<UnitTest*>& getAllTests();
+
+ //==============================================================================
+ /** You can optionally implement this method to set up your test.
+ This method will be called before runTest().
+ */
+ virtual void initialise();
+
+ /** You can optionally implement this method to clear up after your test has been run.
+ This method will be called after runTest() has returned.
+ */
+ virtual void shutdown();
+
+ /** Implement this method in your subclass to actually run your tests.
+
+ The content of your implementation should call beginTest() and expect()
+ to perform the tests.
+ */
+ virtual void runTest() = 0;
+
+ //==============================================================================
+ /** Tells the system that a new subsection of tests is beginning.
+ This should be called from your runTest() method, and may be called
+ as many times as you like, to demarcate different sets of tests.
+ */
+ void beginTest (const String& testName);
+
+ //==============================================================================
+ /** Checks that the result of a test is true, and logs this result.
+
+ In your runTest() method, you should call this method for each condition that
+ you want to check, e.g.
+
+ @code
+ void runTest()
+ {
+ beginTest ("basic tests");
+ expect (x + y == 2);
+ expect (getThing() == someThing);
+ ...etc...
+ }
+ @endcode
+
+ If testResult is true, a pass is logged; if it's false, a failure is logged.
+ If the failure message is specified, it will be written to the log if the test fails.
+ */
+ void expect (bool testResult, const String& failureMessage = String::empty);
+
+ /** Compares two values, and if they don't match, prints out a message containing the
+ expected and actual result values.
+ */
+ template <class ValueType>
+ void expectEquals (ValueType actual, ValueType expected, String failureMessage = String::empty)
+ {
+ const bool result = (actual == expected);
+
+ if (! result)
+ {
+ if (failureMessage.isNotEmpty())
+ failureMessage << " -- ";
+
+ failureMessage << "Expected value: " << expected << ", Actual value: " << actual;
+ }
+
+ expect (result, failureMessage);
+ }
+
+ //==============================================================================
+ /** Writes a message to the test log.
+ This can only be called from within your runTest() method.
+ */
+ void logMessage (const String& message);
+
+ /** Returns a shared RNG that all unit tests should use.
+ If a test needs random numbers, it's important that when an error is found, the
+ exact circumstances can be re-created in order to re-test the problem, by
+ repeating the test with the same random seed value.
+ To make this possible, the UnitTestRunner class creates a master seed value
+ for the run, writes this number to the log, and then this method returns a
+ Random object based on that seed. All tests should only use this method to
+ create any Random objects that they need.
+
+ Note that this method will return an identical object each time it's called
+ for a given run, so if you need several different Random objects, the best
+ way to do that is to call Random::combineSeed() on the result to permute it
+ with a constant value.
+ */
+ Random getRandom() const;
+
+private:
+ //==============================================================================
+ const String name;
+ UnitTestRunner* runner;
+
+ JUCE_DECLARE_NON_COPYABLE (UnitTest)
+};
+
+
+//==============================================================================
+/**
+ Runs a set of unit tests.
+
+ You can instantiate one of these objects and use it to invoke tests on a set of
+ UnitTest objects.
+
+ By using a subclass of UnitTestRunner, you can intercept logging messages and
+ perform custom behaviour when each test completes.
+
+ @see UnitTest
+*/
+class JUCE_API UnitTestRunner
+{
+public:
+ //==============================================================================
+ /** */
+ UnitTestRunner();
+
+ /** Destructor. */
+ virtual ~UnitTestRunner();
+
+ /** Runs a set of tests.
+
+ The tests are performed in order, and the results are logged. To run all the
+ registered UnitTest objects that exist, use runAllTests().
+
+ If you want to run the tests with a predetermined seed, you can pass that into
+ the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
+ */
+ void runTests (const Array<UnitTest*>& tests, int64 randomSeed = 0);
+
+ /** Runs all the UnitTest objects that currently exist.
+ This calls runTests() for all the objects listed in UnitTest::getAllTests().
+
+ If you want to run the tests with a predetermined seed, you can pass that into
+ the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
+ */
+ void runAllTests (int64 randomSeed = 0);
+
+ /** Sets a flag to indicate whether an assertion should be triggered if a test fails.
+ This is true by default.
+ */
+ void setAssertOnFailure (bool shouldAssert) noexcept;
+
+ /** Sets a flag to indicate whether successful tests should be logged.
+ By default, this is set to false, so that only failures will be displayed in the log.
+ */
+ void setPassesAreLogged (bool shouldDisplayPasses) noexcept;
+
+ //==============================================================================
+ /** Contains the results of a test.
+
+ One of these objects is instantiated each time UnitTest::beginTest() is called, and
+ it contains details of the number of subsequent UnitTest::expect() calls that are
+ made.
+ */
+ struct TestResult
+ {
+ /** The main name of this test (i.e. the name of the UnitTest object being run). */
+ String unitTestName;
+ /** The name of the current subcategory (i.e. the name that was set when UnitTest::beginTest() was called). */
+ String subcategoryName;
+
+ /** The number of UnitTest::expect() calls that succeeded. */
+ int passes;
+ /** The number of UnitTest::expect() calls that failed. */
+ int failures;
+
+ /** A list of messages describing the failed tests. */
+ StringArray messages;
+ };
+
+ /** Returns the number of TestResult objects that have been performed.
+ @see getResult
+ */
+ int getNumResults() const noexcept;
+
+ /** Returns one of the TestResult objects that describes a test that has been run.
+ @see getNumResults
+ */
+ const TestResult* getResult (int index) const noexcept;
+
+protected:
+ /** Called when the list of results changes.
+ You can override this to perform some sort of behaviour when results are added.
+ */
+ virtual void resultsUpdated();
+
+ /** Logs a message about the current test progress.
+ By default this just writes the message to the Logger class, but you could override
+ this to do something else with the data.
+ */
+ virtual void logMessage (const String& message);
+
+ /** This can be overridden to let the runner know that it should abort the tests
+ as soon as possible, e.g. because the thread needs to stop.
+ */
+ virtual bool shouldAbortTests();
+
+private:
+ //==============================================================================
+ friend class UnitTest;
+
+ UnitTest* currentTest;
+ String currentSubCategory;
+ OwnedArray <TestResult, CriticalSection> results;
+ bool assertOnFailure, logPasses;
+ Random randomForTest;
+
+ void beginNewTest (UnitTest* test, const String& subCategory);
+ void endTest();
+
+ void addPass();
+ void addFail (const String& failureMessage);
+
+ JUCE_DECLARE_NON_COPYABLE (UnitTestRunner)
+};
+
+
+#endif // JUCE_UNITTEST_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.cpp
new file mode 100644
index 0000000..2eab527
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.cpp
@@ -0,0 +1,891 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+XmlDocument::XmlDocument (const String& documentText)
+ : originalText (documentText),
+ input (nullptr),
+ outOfData (false),
+ errorOccurred (false),
+ needToLoadDTD (false),
+ ignoreEmptyTextElements (true)
+{
+}
+
+XmlDocument::XmlDocument (const File& file)
+ : input (nullptr),
+ outOfData (false),
+ errorOccurred (false),
+ needToLoadDTD (false),
+ ignoreEmptyTextElements (true),
+ inputSource (new FileInputSource (file))
+{
+}
+
+XmlDocument::~XmlDocument()
+{
+}
+
+XmlElement* XmlDocument::parse (const File& file)
+{
+ XmlDocument doc (file);
+ return doc.getDocumentElement();
+}
+
+XmlElement* XmlDocument::parse (const String& xmlData)
+{
+ XmlDocument doc (xmlData);
+ return doc.getDocumentElement();
+}
+
+void XmlDocument::setInputSource (InputSource* const newSource) noexcept
+{
+ inputSource = newSource;
+}
+
+void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) noexcept
+{
+ ignoreEmptyTextElements = shouldBeIgnored;
+}
+
+namespace XmlIdentifierChars
+{
+ static bool isIdentifierCharSlow (const juce_wchar c) noexcept
+ {
+ return CharacterFunctions::isLetterOrDigit (c)
+ || c == '_' || c == '-' || c == ':' || c == '.';
+ }
+
+ static bool isIdentifierChar (const juce_wchar c) noexcept
+ {
+ static const uint32 legalChars[] = { 0, 0x7ff6000, 0x87fffffe, 0x7fffffe, 0 };
+
+ return ((int) c < (int) numElementsInArray (legalChars) * 32) ? ((legalChars [c >> 5] & (1 << (c & 31))) != 0)
+ : isIdentifierCharSlow (c);
+ }
+
+ /*static void generateIdentifierCharConstants()
+ {
+ uint32 n[8] = { 0 };
+ for (int i = 0; i < 256; ++i)
+ if (isIdentifierCharSlow (i))
+ n[i >> 5] |= (1 << (i & 31));
+
+ String s;
+ for (int i = 0; i < 8; ++i)
+ s << "0x" << String::toHexString ((int) n[i]) << ", ";
+
+ DBG (s);
+ }*/
+
+ static String::CharPointerType findEndOfToken (String::CharPointerType p)
+ {
+ while (isIdentifierChar (*p))
+ ++p;
+
+ return p;
+ }
+}
+
+XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement)
+{
+ if (originalText.isEmpty() && inputSource != nullptr)
+ {
+ ScopedPointer<InputStream> in (inputSource->createInputStream());
+
+ if (in != nullptr)
+ {
+ MemoryOutputStream data;
+ data.writeFromInputStream (*in, onlyReadOuterDocumentElement ? 8192 : -1);
+
+ #if JUCE_STRING_UTF_TYPE == 8
+ if (data.getDataSize() > 2)
+ {
+ data.writeByte (0);
+ const char* text = static_cast<const char*> (data.getData());
+
+ if (CharPointer_UTF16::isByteOrderMarkBigEndian (text)
+ || CharPointer_UTF16::isByteOrderMarkLittleEndian (text))
+ {
+ originalText = data.toString();
+ }
+ else
+ {
+ if (CharPointer_UTF8::isByteOrderMark (text))
+ text += 3;
+
+ // parse the input buffer directly to avoid copying it all to a string..
+ return parseDocumentElement (String::CharPointerType (text), onlyReadOuterDocumentElement);
+ }
+ }
+ #else
+ originalText = data.toString();
+ #endif
+ }
+ }
+
+ return parseDocumentElement (originalText.getCharPointer(), onlyReadOuterDocumentElement);
+}
+
+const String& XmlDocument::getLastParseError() const noexcept
+{
+ return lastError;
+}
+
+void XmlDocument::setLastError (const String& desc, const bool carryOn)
+{
+ lastError = desc;
+ errorOccurred = ! carryOn;
+}
+
+String XmlDocument::getFileContents (const String& filename) const
+{
+ if (inputSource != nullptr)
+ {
+ const ScopedPointer<InputStream> in (inputSource->createInputStreamFor (filename.trim().unquoted()));
+
+ if (in != nullptr)
+ return in->readEntireStreamAsString();
+ }
+
+ return String::empty;
+}
+
+juce_wchar XmlDocument::readNextChar() noexcept
+{
+ const juce_wchar c = input.getAndAdvance();
+
+ if (c == 0)
+ {
+ outOfData = true;
+ --input;
+ }
+
+ return c;
+}
+
+XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToParse,
+ const bool onlyReadOuterDocumentElement)
+{
+ input = textToParse;
+ errorOccurred = false;
+ outOfData = false;
+ needToLoadDTD = true;
+
+ if (textToParse.isEmpty())
+ {
+ lastError = "not enough input";
+ }
+ else if (! parseHeader())
+ {
+ lastError = "malformed header";
+ }
+ else if (! parseDTD())
+ {
+ lastError = "malformed DTD";
+ }
+ else
+ {
+ lastError.clear();
+
+ ScopedPointer<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement));
+
+ if (! errorOccurred)
+ return result.release();
+ }
+
+ return nullptr;
+}
+
+bool XmlDocument::parseHeader()
+{
+ skipNextWhiteSpace();
+
+ if (CharacterFunctions::compareUpTo (input, CharPointer_ASCII ("<?xml"), 5) == 0)
+ {
+ const String::CharPointerType headerEnd (CharacterFunctions::find (input, CharPointer_ASCII ("?>")));
+
+ if (headerEnd.isEmpty())
+ return false;
+
+ #if JUCE_DEBUG
+ const String encoding (String (input, headerEnd)
+ .fromFirstOccurrenceOf ("encoding", false, true)
+ .fromFirstOccurrenceOf ("=", false, false)
+ .fromFirstOccurrenceOf ("\"", false, false)
+ .upToFirstOccurrenceOf ("\"", false, false).trim());
+
+ /* If you load an XML document with a non-UTF encoding type, it may have been
+ loaded wrongly.. Since all the files are read via the normal juce file streams,
+ they're treated as UTF-8, so by the time it gets to the parser, the encoding will
+ have been lost. Best plan is to stick to utf-8 or if you have specific files to
+ read, use your own code to convert them to a unicode String, and pass that to the
+ XML parser.
+ */
+ jassert (encoding.isEmpty() || encoding.startsWithIgnoreCase ("utf-"));
+ #endif
+
+ input = headerEnd + 2;
+ skipNextWhiteSpace();
+ }
+
+ return true;
+}
+
+bool XmlDocument::parseDTD()
+{
+ if (CharacterFunctions::compareUpTo (input, CharPointer_ASCII ("<!DOCTYPE"), 9) == 0)
+ {
+ input += 9;
+ const String::CharPointerType dtdStart (input);
+
+ for (int n = 1; n > 0;)
+ {
+ const juce_wchar c = readNextChar();
+
+ if (outOfData)
+ return false;
+
+ if (c == '<')
+ ++n;
+ else if (c == '>')
+ --n;
+ }
+
+ dtdText = String (dtdStart, input - 1).trim();
+ }
+
+ return true;
+}
+
+void XmlDocument::skipNextWhiteSpace()
+{
+ for (;;)
+ {
+ input = input.findEndOfWhitespace();
+
+ if (input.isEmpty())
+ {
+ outOfData = true;
+ break;
+ }
+
+ if (*input == '<')
+ {
+ if (input[1] == '!'
+ && input[2] == '-'
+ && input[3] == '-')
+ {
+ input += 4;
+ const int closeComment = input.indexOf (CharPointer_ASCII ("-->"));
+
+ if (closeComment < 0)
+ {
+ outOfData = true;
+ break;
+ }
+
+ input += closeComment + 3;
+ continue;
+ }
+
+ if (input[1] == '?')
+ {
+ input += 2;
+ const int closeBracket = input.indexOf (CharPointer_ASCII ("?>"));
+
+ if (closeBracket < 0)
+ {
+ outOfData = true;
+ break;
+ }
+
+ input += closeBracket + 2;
+ continue;
+ }
+ }
+
+ break;
+ }
+}
+
+void XmlDocument::readQuotedString (String& result)
+{
+ const juce_wchar quote = readNextChar();
+
+ while (! outOfData)
+ {
+ const juce_wchar c = readNextChar();
+
+ if (c == quote)
+ break;
+
+ --input;
+
+ if (c == '&')
+ {
+ readEntity (result);
+ }
+ else
+ {
+ const String::CharPointerType start (input);
+
+ for (;;)
+ {
+ const juce_wchar character = *input;
+
+ if (character == quote)
+ {
+ result.appendCharPointer (start, input);
+ ++input;
+ return;
+ }
+ else if (character == '&')
+ {
+ result.appendCharPointer (start, input);
+ break;
+ }
+ else if (character == 0)
+ {
+ setLastError ("unmatched quotes", false);
+ outOfData = true;
+ break;
+ }
+
+ ++input;
+ }
+ }
+ }
+}
+
+XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements)
+{
+ XmlElement* node = nullptr;
+
+ skipNextWhiteSpace();
+ if (outOfData)
+ return nullptr;
+
+ if (*input == '<')
+ {
+ ++input;
+ String::CharPointerType endOfToken (XmlIdentifierChars::findEndOfToken (input));
+
+ if (endOfToken == input)
+ {
+ // no tag name - but allow for a gap after the '<' before giving an error
+ skipNextWhiteSpace();
+ endOfToken = XmlIdentifierChars::findEndOfToken (input);
+
+ if (endOfToken == input)
+ {
+ setLastError ("tag name missing", false);
+ return node;
+ }
+ }
+
+ node = new XmlElement (input, endOfToken);
+ input = endOfToken;
+ LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes);
+
+ // look for attributes
+ for (;;)
+ {
+ skipNextWhiteSpace();
+
+ const juce_wchar c = *input;
+
+ // empty tag..
+ if (c == '/' && input[1] == '>')
+ {
+ input += 2;
+ break;
+ }
+
+ // parse the guts of the element..
+ if (c == '>')
+ {
+ ++input;
+
+ if (alsoParseSubElements)
+ readChildElements (*node);
+
+ break;
+ }
+
+ // get an attribute..
+ if (XmlIdentifierChars::isIdentifierChar (c))
+ {
+ String::CharPointerType attNameEnd (XmlIdentifierChars::findEndOfToken (input));
+
+ if (attNameEnd != input)
+ {
+ const String::CharPointerType attNameStart (input);
+ input = attNameEnd;
+
+ skipNextWhiteSpace();
+
+ if (readNextChar() == '=')
+ {
+ skipNextWhiteSpace();
+
+ const juce_wchar nextChar = *input;
+
+ if (nextChar == '"' || nextChar == '\'')
+ {
+ XmlElement::XmlAttributeNode* const newAtt
+ = new XmlElement::XmlAttributeNode (attNameStart, attNameEnd);
+
+ readQuotedString (newAtt->value);
+ attributeAppender.append (newAtt);
+ continue;
+ }
+ }
+ else
+ {
+ setLastError ("expected '=' after attribute '"
+ + String (attNameStart, attNameEnd) + "'", false);
+ return node;
+ }
+ }
+ }
+ else
+ {
+ if (! outOfData)
+ setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false);
+ }
+
+ break;
+ }
+ }
+
+ return node;
+}
+
+void XmlDocument::readChildElements (XmlElement& parent)
+{
+ LinkedListPointer<XmlElement>::Appender childAppender (parent.firstChildElement);
+
+ for (;;)
+ {
+ const String::CharPointerType preWhitespaceInput (input);
+ skipNextWhiteSpace();
+
+ if (outOfData)
+ {
+ setLastError ("unmatched tags", false);
+ break;
+ }
+
+ if (*input == '<')
+ {
+ const juce_wchar c1 = input[1];
+
+ if (c1 == '/')
+ {
+ // our close tag..
+ const int closeTag = input.indexOf ((juce_wchar) '>');
+
+ if (closeTag >= 0)
+ input += closeTag + 1;
+
+ break;
+ }
+
+ if (c1 == '!' && CharacterFunctions::compareUpTo (input + 2, CharPointer_ASCII ("[CDATA["), 7) == 0)
+ {
+ input += 9;
+ const String::CharPointerType inputStart (input);
+
+ for (;;)
+ {
+ const juce_wchar c0 = *input;
+
+ if (c0 == 0)
+ {
+ setLastError ("unterminated CDATA section", false);
+ outOfData = true;
+ break;
+ }
+ else if (c0 == ']'
+ && input[1] == ']'
+ && input[2] == '>')
+ {
+ childAppender.append (XmlElement::createTextElement (String (inputStart, input)));
+ input += 3;
+ break;
+ }
+
+ ++input;
+ }
+ }
+ else
+ {
+ // this is some other element, so parse and add it..
+ if (XmlElement* const n = readNextElement (true))
+ childAppender.append (n);
+ else
+ break;
+ }
+ }
+ else // must be a character block
+ {
+ input = preWhitespaceInput; // roll back to include the leading whitespace
+ String textElementContent;
+
+ for (;;)
+ {
+ const juce_wchar c = *input;
+
+ if (c == '<')
+ {
+ if (input[1] == '!' && input[2] == '-' && input[3] == '-')
+ {
+ input += 4;
+ const int closeComment = input.indexOf (CharPointer_ASCII ("-->"));
+
+ if (closeComment < 0)
+ {
+ setLastError ("unterminated comment", false);
+ outOfData = true;
+ return;
+ }
+
+ input += closeComment + 3;
+ continue;
+ }
+
+ break;
+ }
+
+ if (c == 0)
+ {
+ setLastError ("unmatched tags", false);
+ outOfData = true;
+ return;
+ }
+
+ if (c == '&')
+ {
+ String entity;
+ readEntity (entity);
+
+ if (entity.startsWithChar ('<') && entity [1] != 0)
+ {
+ const String::CharPointerType oldInput (input);
+ const bool oldOutOfData = outOfData;
+
+ input = entity.getCharPointer();
+ outOfData = false;
+
+ for (;;)
+ {
+ XmlElement* const n = readNextElement (true);
+
+ if (n == nullptr)
+ break;
+
+ childAppender.append (n);
+ }
+
+ input = oldInput;
+ outOfData = oldOutOfData;
+ }
+ else
+ {
+ textElementContent += entity;
+ }
+ }
+ else
+ {
+ const String::CharPointerType start (input);
+
+ for (;;)
+ {
+ const juce_wchar nextChar = *input;
+
+ if (nextChar == '<' || nextChar == '&')
+ break;
+
+ if (nextChar == 0)
+ {
+ setLastError ("unmatched tags", false);
+ outOfData = true;
+ return;
+ }
+
+ ++input;
+ }
+
+ textElementContent.appendCharPointer (start, input);
+ }
+ }
+
+ if ((! ignoreEmptyTextElements) || textElementContent.containsNonWhitespaceChars())
+ childAppender.append (XmlElement::createTextElement (textElementContent));
+ }
+ }
+}
+
+void XmlDocument::readEntity (String& result)
+{
+ // skip over the ampersand
+ ++input;
+
+ if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("amp;"), 4) == 0)
+ {
+ input += 4;
+ result += '&';
+ }
+ else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("quot;"), 5) == 0)
+ {
+ input += 5;
+ result += '"';
+ }
+ else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("apos;"), 5) == 0)
+ {
+ input += 5;
+ result += '\'';
+ }
+ else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("lt;"), 3) == 0)
+ {
+ input += 3;
+ result += '<';
+ }
+ else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("gt;"), 3) == 0)
+ {
+ input += 3;
+ result += '>';
+ }
+ else if (*input == '#')
+ {
+ int charCode = 0;
+ ++input;
+
+ if (*input == 'x' || *input == 'X')
+ {
+ ++input;
+ int numChars = 0;
+
+ while (input[0] != ';')
+ {
+ const int hexValue = CharacterFunctions::getHexDigitValue (input[0]);
+
+ if (hexValue < 0 || ++numChars > 8)
+ {
+ setLastError ("illegal escape sequence", true);
+ break;
+ }
+
+ charCode = (charCode << 4) | hexValue;
+ ++input;
+ }
+
+ ++input;
+ }
+ else if (input[0] >= '0' && input[0] <= '9')
+ {
+ int numChars = 0;
+
+ while (input[0] != ';')
+ {
+ if (++numChars > 12)
+ {
+ setLastError ("illegal escape sequence", true);
+ break;
+ }
+
+ charCode = charCode * 10 + ((int) input[0] - '0');
+ ++input;
+ }
+
+ ++input;
+ }
+ else
+ {
+ setLastError ("illegal escape sequence", true);
+ result += '&';
+ return;
+ }
+
+ result << (juce_wchar) charCode;
+ }
+ else
+ {
+ const String::CharPointerType entityNameStart (input);
+ const int closingSemiColon = input.indexOf ((juce_wchar) ';');
+
+ if (closingSemiColon < 0)
+ {
+ outOfData = true;
+ result += '&';
+ }
+ else
+ {
+ input += closingSemiColon + 1;
+
+ result += expandExternalEntity (String (entityNameStart, (size_t) closingSemiColon));
+ }
+ }
+}
+
+String XmlDocument::expandEntity (const String& ent)
+{
+ if (ent.equalsIgnoreCase ("amp")) return String::charToString ('&');
+ if (ent.equalsIgnoreCase ("quot")) return String::charToString ('"');
+ if (ent.equalsIgnoreCase ("apos")) return String::charToString ('\'');
+ if (ent.equalsIgnoreCase ("lt")) return String::charToString ('<');
+ if (ent.equalsIgnoreCase ("gt")) return String::charToString ('>');
+
+ if (ent[0] == '#')
+ {
+ const juce_wchar char1 = ent[1];
+
+ if (char1 == 'x' || char1 == 'X')
+ return String::charToString (static_cast <juce_wchar> (ent.substring (2).getHexValue32()));
+
+ if (char1 >= '0' && char1 <= '9')
+ return String::charToString (static_cast <juce_wchar> (ent.substring (1).getIntValue()));
+
+ setLastError ("illegal escape sequence", false);
+ return String::charToString ('&');
+ }
+
+ return expandExternalEntity (ent);
+}
+
+String XmlDocument::expandExternalEntity (const String& entity)
+{
+ if (needToLoadDTD)
+ {
+ if (dtdText.isNotEmpty())
+ {
+ dtdText = dtdText.trimCharactersAtEnd (">");
+ tokenisedDTD.addTokens (dtdText, true);
+
+ if (tokenisedDTD [tokenisedDTD.size() - 2].equalsIgnoreCase ("system")
+ && tokenisedDTD [tokenisedDTD.size() - 1].isQuotedString())
+ {
+ const String fn (tokenisedDTD [tokenisedDTD.size() - 1]);
+
+ tokenisedDTD.clear();
+ tokenisedDTD.addTokens (getFileContents (fn), true);
+ }
+ else
+ {
+ tokenisedDTD.clear();
+ const int openBracket = dtdText.indexOfChar ('[');
+
+ if (openBracket > 0)
+ {
+ const int closeBracket = dtdText.lastIndexOfChar (']');
+
+ if (closeBracket > openBracket)
+ tokenisedDTD.addTokens (dtdText.substring (openBracket + 1,
+ closeBracket), true);
+ }
+ }
+
+ for (int i = tokenisedDTD.size(); --i >= 0;)
+ {
+ if (tokenisedDTD[i].startsWithChar ('%')
+ && tokenisedDTD[i].endsWithChar (';'))
+ {
+ const String parsed (getParameterEntity (tokenisedDTD[i].substring (1, tokenisedDTD[i].length() - 1)));
+ StringArray newToks;
+ newToks.addTokens (parsed, true);
+
+ tokenisedDTD.remove (i);
+
+ for (int j = newToks.size(); --j >= 0;)
+ tokenisedDTD.insert (i, newToks[j]);
+ }
+ }
+ }
+
+ needToLoadDTD = false;
+ }
+
+ for (int i = 0; i < tokenisedDTD.size(); ++i)
+ {
+ if (tokenisedDTD[i] == entity)
+ {
+ if (tokenisedDTD[i - 1].equalsIgnoreCase ("<!entity"))
+ {
+ String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">").trim().unquoted());
+
+ // check for sub-entities..
+ int ampersand = ent.indexOfChar ('&');
+
+ while (ampersand >= 0)
+ {
+ const int semiColon = ent.indexOf (i + 1, ";");
+
+ if (semiColon < 0)
+ {
+ setLastError ("entity without terminating semi-colon", false);
+ break;
+ }
+
+ const String resolved (expandEntity (ent.substring (i + 1, semiColon)));
+
+ ent = ent.substring (0, ampersand)
+ + resolved
+ + ent.substring (semiColon + 1);
+
+ ampersand = ent.indexOfChar (semiColon + 1, '&');
+ }
+
+ return ent;
+ }
+ }
+ }
+
+ setLastError ("unknown entity", true);
+
+ return entity;
+}
+
+String XmlDocument::getParameterEntity (const String& entity)
+{
+ for (int i = 0; i < tokenisedDTD.size(); ++i)
+ {
+ if (tokenisedDTD[i] == entity
+ && tokenisedDTD [i - 1] == "%"
+ && tokenisedDTD [i - 2].equalsIgnoreCase ("<!entity"))
+ {
+ const String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">"));
+
+ if (ent.equalsIgnoreCase ("system"))
+ return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">"));
+
+ return ent.trim().unquoted();
+ }
+ }
+
+ return entity;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.h b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.h
new file mode 100644
index 0000000..d2a5b49
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlDocument.h
@@ -0,0 +1,181 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_XMLDOCUMENT_H_INCLUDED
+#define JUCE_XMLDOCUMENT_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Parses a text-based XML document and creates an XmlElement object from it.
+
+ The parser will parse DTDs to load external entities but won't
+ check the document for validity against the DTD.
+
+ e.g.
+ @code
+
+ XmlDocument myDocument (File ("myfile.xml"));
+ XmlElement* mainElement = myDocument.getDocumentElement();
+
+ if (mainElement == nullptr)
+ {
+ String error = myDocument.getLastParseError();
+ }
+ else
+ {
+ ..use the element
+ }
+
+ @endcode
+
+ Or you can use the static helper methods for quick parsing..
+
+ @code
+ XmlElement* xml = XmlDocument::parse (myXmlFile);
+
+ if (xml != nullptr && xml->hasTagName ("foobar"))
+ {
+ ...etc
+ @endcode
+
+ @see XmlElement
+*/
+class JUCE_API XmlDocument
+{
+public:
+ //==============================================================================
+ /** Creates an XmlDocument from the xml text.
+ The text doesn't actually get parsed until the getDocumentElement() method is called.
+ */
+ XmlDocument (const String& documentText);
+
+ /** Creates an XmlDocument from a file.
+ The text doesn't actually get parsed until the getDocumentElement() method is called.
+ */
+ XmlDocument (const File& file);
+
+ /** Destructor. */
+ ~XmlDocument();
+
+ //==============================================================================
+ /** Creates an XmlElement object to represent the main document node.
+
+ This method will do the actual parsing of the text, and if there's a
+ parse error, it may returns nullptr (and you can find out the error using
+ the getLastParseError() method).
+
+ See also the parse() methods, which provide a shorthand way to quickly
+ parse a file or string.
+
+ @param onlyReadOuterDocumentElement if true, the parser will only read the
+ first section of the file, and will only
+ return the outer document element - this
+ allows quick checking of large files to
+ see if they contain the correct type of
+ tag, without having to parse the entire file
+ @returns a new XmlElement which the caller will need to delete, or null if
+ there was an error.
+ @see getLastParseError
+ */
+ XmlElement* getDocumentElement (bool onlyReadOuterDocumentElement = false);
+
+ /** Returns the parsing error that occurred the last time getDocumentElement was called.
+
+ @returns the error, or an empty string if there was no error.
+ */
+ const String& getLastParseError() const noexcept;
+
+ /** Sets an input source object to use for parsing documents that reference external entities.
+
+ If the document has been created from a file, this probably won't be needed, but
+ if you're parsing some text and there might be a DTD that references external
+ files, you may need to create a custom input source that can retrieve the
+ other files it needs.
+
+ The object that is passed-in will be deleted automatically when no longer needed.
+
+ @see InputSource
+ */
+ void setInputSource (InputSource* newSource) noexcept;
+
+ /** Sets a flag to change the treatment of empty text elements.
+
+ If this is true (the default state), then any text elements that contain only
+ whitespace characters will be ingored during parsing. If you need to catch
+ whitespace-only text, then you should set this to false before calling the
+ getDocumentElement() method.
+ */
+ void setEmptyTextElementsIgnored (bool shouldBeIgnored) noexcept;
+
+ //==============================================================================
+ /** A handy static method that parses a file.
+ This is a shortcut for creating an XmlDocument object and calling getDocumentElement() on it.
+ @returns a new XmlElement which the caller will need to delete, or null if there was an error.
+ */
+ static XmlElement* parse (const File& file);
+
+ /** A handy static method that parses some XML data.
+ This is a shortcut for creating an XmlDocument object and calling getDocumentElement() on it.
+ @returns a new XmlElement which the caller will need to delete, or null if there was an error.
+ */
+ static XmlElement* parse (const String& xmlData);
+
+
+ //==============================================================================
+private:
+ String originalText;
+ String::CharPointerType input;
+ bool outOfData, errorOccurred;
+
+ String lastError, dtdText;
+ StringArray tokenisedDTD;
+ bool needToLoadDTD, ignoreEmptyTextElements;
+ ScopedPointer<InputSource> inputSource;
+
+ XmlElement* parseDocumentElement (String::CharPointerType, bool outer);
+ void setLastError (const String&, bool carryOn);
+ bool parseHeader();
+ bool parseDTD();
+ void skipNextWhiteSpace();
+ juce_wchar readNextChar() noexcept;
+ XmlElement* readNextElement (bool alsoParseSubElements);
+ void readChildElements (XmlElement&);
+ void readQuotedString (String&);
+ void readEntity (String&);
+
+ String getFileContents (const String&) const;
+ String expandEntity (const String&);
+ String expandExternalEntity (const String&);
+ String getParameterEntity (const String&);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XmlDocument)
+};
+
+
+#endif // JUCE_XMLDOCUMENT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.cpp
new file mode 100644
index 0000000..000df15
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.cpp
@@ -0,0 +1,888 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+XmlElement::XmlAttributeNode::XmlAttributeNode (const XmlAttributeNode& other) noexcept
+ : name (other.name),
+ value (other.value)
+{
+}
+
+XmlElement::XmlAttributeNode::XmlAttributeNode (const Identifier& n, const String& v) noexcept
+ : name (n), value (v)
+{
+ #if JUCE_DEBUG
+ // this checks whether the attribute name string contains any illegal characters..
+ for (String::CharPointerType t (name.getCharPointer()); ! t.isEmpty(); ++t)
+ jassert (t.isLetterOrDigit() || *t == '_' || *t == '-' || *t == ':');
+ #endif
+}
+
+XmlElement::XmlAttributeNode::XmlAttributeNode (String::CharPointerType nameStart, String::CharPointerType nameEnd)
+ : name (nameStart, nameEnd)
+{
+}
+
+//==============================================================================
+static void sanityCheckTagName (const String& tag)
+{
+ (void) tag;
+
+ // the tag name mustn't be empty, or it'll look like a text element!
+ jassert (tag.containsNonWhitespaceChars())
+
+ // The tag can't contain spaces or other characters that would create invalid XML!
+ jassert (! tag.containsAnyOf (" <>/&(){}"));
+}
+
+XmlElement::XmlElement (const String& tag)
+ : tagName (StringPool::getGlobalPool().getPooledString (tag))
+{
+ sanityCheckTagName (tagName);
+}
+
+XmlElement::XmlElement (const char* tag)
+ : tagName (StringPool::getGlobalPool().getPooledString (tag))
+{
+ sanityCheckTagName (tagName);
+}
+
+XmlElement::XmlElement (StringRef tag)
+ : tagName (StringPool::getGlobalPool().getPooledString (tag))
+{
+ sanityCheckTagName (tagName);
+}
+
+XmlElement::XmlElement (const Identifier& tag)
+ : tagName (tag.toString())
+{
+ sanityCheckTagName (tagName);
+}
+
+XmlElement::XmlElement (String::CharPointerType tagNameStart, String::CharPointerType tagNameEnd)
+ : tagName (StringPool::getGlobalPool().getPooledString (tagNameStart, tagNameEnd))
+{
+ sanityCheckTagName (tagName);
+}
+
+XmlElement::XmlElement (int /*dummy*/) noexcept
+{
+}
+
+XmlElement::XmlElement (const XmlElement& other)
+ : tagName (other.tagName)
+{
+ copyChildrenAndAttributesFrom (other);
+}
+
+XmlElement& XmlElement::operator= (const XmlElement& other)
+{
+ if (this != &other)
+ {
+ removeAllAttributes();
+ deleteAllChildElements();
+ tagName = other.tagName;
+ copyChildrenAndAttributesFrom (other);
+ }
+
+ return *this;
+}
+
+#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+XmlElement::XmlElement (XmlElement&& other) noexcept
+ : nextListItem (static_cast<LinkedListPointer<XmlElement>&&> (other.nextListItem)),
+ firstChildElement (static_cast<LinkedListPointer<XmlElement>&&> (other.firstChildElement)),
+ attributes (static_cast<LinkedListPointer<XmlAttributeNode>&&> (other.attributes)),
+ tagName (static_cast<String&&> (other.tagName))
+{
+}
+
+XmlElement& XmlElement::operator= (XmlElement&& other) noexcept
+{
+ jassert (this != &other); // hopefully the compiler should make this situation impossible!
+
+ removeAllAttributes();
+ deleteAllChildElements();
+
+ nextListItem = static_cast<LinkedListPointer<XmlElement>&&> (other.nextListItem);
+ firstChildElement = static_cast<LinkedListPointer<XmlElement>&&> (other.firstChildElement);
+ attributes = static_cast<LinkedListPointer<XmlAttributeNode>&&> (other.attributes);
+ tagName = static_cast<String&&> (other.tagName);
+
+ return *this;
+}
+#endif
+
+void XmlElement::copyChildrenAndAttributesFrom (const XmlElement& other)
+{
+ jassert (firstChildElement.get() == nullptr);
+ firstChildElement.addCopyOfList (other.firstChildElement);
+
+ jassert (attributes.get() == nullptr);
+ attributes.addCopyOfList (other.attributes);
+}
+
+XmlElement::~XmlElement() noexcept
+{
+ firstChildElement.deleteAll();
+ attributes.deleteAll();
+}
+
+//==============================================================================
+namespace XmlOutputFunctions
+{
+ #if 0 // (These functions are just used to generate the lookup table used below)
+ bool isLegalXmlCharSlow (const juce_wchar character) noexcept
+ {
+ if ((character >= 'a' && character <= 'z')
+ || (character >= 'A' && character <= 'Z')
+ || (character >= '0' && character <= '9'))
+ return true;
+
+ const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}$|";
+
+ do
+ {
+ if (((juce_wchar) (uint8) *t) == character)
+ return true;
+ }
+ while (*++t != 0);
+
+ return false;
+ }
+
+ void generateLegalCharLookupTable()
+ {
+ uint8 n[32] = { 0 };
+ for (int i = 0; i < 256; ++i)
+ if (isLegalXmlCharSlow (i))
+ n[i >> 3] |= (1 << (i & 7));
+
+ String s;
+ for (int i = 0; i < 32; ++i)
+ s << (int) n[i] << ", ";
+
+ DBG (s);
+ }
+ #endif
+
+ static bool isLegalXmlChar (const uint32 c) noexcept
+ {
+ static const unsigned char legalChars[] = { 0, 0, 0, 0, 187, 255, 255, 175, 255,
+ 255, 255, 191, 254, 255, 255, 127 };
+ return c < sizeof (legalChars) * 8
+ && (legalChars [c >> 3] & (1 << (c & 7))) != 0;
+ }
+
+ static void escapeIllegalXmlChars (OutputStream& outputStream, const String& text, const bool changeNewLines)
+ {
+ String::CharPointerType t (text.getCharPointer());
+
+ for (;;)
+ {
+ const uint32 character = (uint32) t.getAndAdvance();
+
+ if (character == 0)
+ break;
+
+ if (isLegalXmlChar (character))
+ {
+ outputStream << (char) character;
+ }
+ else
+ {
+ switch (character)
+ {
+ case '&': outputStream << "&"; break;
+ case '"': outputStream << """; break;
+ case '>': outputStream << ">"; break;
+ case '<': outputStream << "<"; break;
+
+ case '\n':
+ case '\r':
+ if (! changeNewLines)
+ {
+ outputStream << (char) character;
+ break;
+ }
+ // Note: deliberate fall-through here!
+ default:
+ outputStream << "&#" << ((int) character) << ';';
+ break;
+ }
+ }
+ }
+ }
+
+ static void writeSpaces (OutputStream& out, const size_t numSpaces)
+ {
+ out.writeRepeatedByte (' ', numSpaces);
+ }
+}
+
+void XmlElement::writeElementAsText (OutputStream& outputStream,
+ const int indentationLevel,
+ const int lineWrapLength) const
+{
+ using namespace XmlOutputFunctions;
+
+ if (indentationLevel >= 0)
+ writeSpaces (outputStream, (size_t) indentationLevel);
+
+ if (! isTextElement())
+ {
+ outputStream.writeByte ('<');
+ outputStream << tagName;
+
+ {
+ const size_t attIndent = (size_t) (indentationLevel + tagName.length() + 1);
+ int lineLen = 0;
+
+ for (const XmlAttributeNode* att = attributes; att != nullptr; att = att->nextListItem)
+ {
+ if (lineLen > lineWrapLength && indentationLevel >= 0)
+ {
+ outputStream << newLine;
+ writeSpaces (outputStream, attIndent);
+ lineLen = 0;
+ }
+
+ const int64 startPos = outputStream.getPosition();
+ outputStream.writeByte (' ');
+ outputStream << att->name;
+ outputStream.write ("=\"", 2);
+ escapeIllegalXmlChars (outputStream, att->value, true);
+ outputStream.writeByte ('"');
+ lineLen += (int) (outputStream.getPosition() - startPos);
+ }
+ }
+
+ if (firstChildElement != nullptr)
+ {
+ outputStream.writeByte ('>');
+
+ bool lastWasTextNode = false;
+
+ for (XmlElement* child = firstChildElement; child != nullptr; child = child->nextListItem)
+ {
+ if (child->isTextElement())
+ {
+ escapeIllegalXmlChars (outputStream, child->getText(), false);
+ lastWasTextNode = true;
+ }
+ else
+ {
+ if (indentationLevel >= 0 && ! lastWasTextNode)
+ outputStream << newLine;
+
+ child->writeElementAsText (outputStream,
+ lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength);
+ lastWasTextNode = false;
+ }
+ }
+
+ if (indentationLevel >= 0 && ! lastWasTextNode)
+ {
+ outputStream << newLine;
+ writeSpaces (outputStream, (size_t) indentationLevel);
+ }
+
+ outputStream.write ("</", 2);
+ outputStream << tagName;
+ outputStream.writeByte ('>');
+ }
+ else
+ {
+ outputStream.write ("/>", 2);
+ }
+ }
+ else
+ {
+ escapeIllegalXmlChars (outputStream, getText(), false);
+ }
+}
+
+String XmlElement::createDocument (StringRef dtdToUse,
+ const bool allOnOneLine,
+ const bool includeXmlHeader,
+ StringRef encodingType,
+ const int lineWrapLength) const
+{
+ MemoryOutputStream mem (2048);
+ writeToStream (mem, dtdToUse, allOnOneLine, includeXmlHeader, encodingType, lineWrapLength);
+
+ return mem.toUTF8();
+}
+
+void XmlElement::writeToStream (OutputStream& output,
+ StringRef dtdToUse,
+ const bool allOnOneLine,
+ const bool includeXmlHeader,
+ StringRef encodingType,
+ const int lineWrapLength) const
+{
+ using namespace XmlOutputFunctions;
+
+ if (includeXmlHeader)
+ {
+ output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>";
+
+ if (allOnOneLine)
+ output.writeByte (' ');
+ else
+ output << newLine << newLine;
+ }
+
+ if (dtdToUse.isNotEmpty())
+ {
+ output << dtdToUse;
+
+ if (allOnOneLine)
+ output.writeByte (' ');
+ else
+ output << newLine;
+ }
+
+ writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength);
+
+ if (! allOnOneLine)
+ output << newLine;
+}
+
+bool XmlElement::writeToFile (const File& file,
+ StringRef dtdToUse,
+ StringRef encodingType,
+ const int lineWrapLength) const
+{
+ TemporaryFile tempFile (file);
+
+ {
+ FileOutputStream out (tempFile.getFile());
+
+ if (! out.openedOk())
+ return false;
+
+ writeToStream (out, dtdToUse, false, true, encodingType, lineWrapLength);
+ }
+
+ return tempFile.overwriteTargetFileWithTemporary();
+}
+
+//==============================================================================
+bool XmlElement::hasTagName (StringRef possibleTagName) const noexcept
+{
+ const bool matches = tagName.equalsIgnoreCase (possibleTagName);
+
+ // XML tags should be case-sensitive, so although this method allows a
+ // case-insensitive match to pass, you should try to avoid this.
+ jassert ((! matches) || tagName == possibleTagName);
+
+ return matches;
+}
+
+String XmlElement::getNamespace() const
+{
+ return tagName.upToFirstOccurrenceOf (":", false, false);
+}
+
+String XmlElement::getTagNameWithoutNamespace() const
+{
+ return tagName.fromLastOccurrenceOf (":", false, false);
+}
+
+bool XmlElement::hasTagNameIgnoringNamespace (StringRef possibleTagName) const
+{
+ return hasTagName (possibleTagName) || getTagNameWithoutNamespace() == possibleTagName;
+}
+
+XmlElement* XmlElement::getNextElementWithTagName (StringRef requiredTagName) const
+{
+ XmlElement* e = nextListItem;
+
+ while (e != nullptr && ! e->hasTagName (requiredTagName))
+ e = e->nextListItem;
+
+ return e;
+}
+
+//==============================================================================
+int XmlElement::getNumAttributes() const noexcept
+{
+ return attributes.size();
+}
+
+const String& XmlElement::getAttributeName (const int index) const noexcept
+{
+ if (const XmlAttributeNode* const att = attributes [index])
+ return att->name.toString();
+
+ return String::empty;
+}
+
+const String& XmlElement::getAttributeValue (const int index) const noexcept
+{
+ if (const XmlAttributeNode* const att = attributes [index])
+ return att->value;
+
+ return String::empty;
+}
+
+XmlElement::XmlAttributeNode* XmlElement::getAttribute (StringRef attributeName) const noexcept
+{
+ for (XmlAttributeNode* att = attributes; att != nullptr; att = att->nextListItem)
+ if (att->name == attributeName)
+ return att;
+
+ return nullptr;
+}
+
+bool XmlElement::hasAttribute (StringRef attributeName) const noexcept
+{
+ return getAttribute (attributeName) != nullptr;
+}
+
+//==============================================================================
+const String& XmlElement::getStringAttribute (StringRef attributeName) const noexcept
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ return att->value;
+
+ return String::empty;
+}
+
+String XmlElement::getStringAttribute (StringRef attributeName, const String& defaultReturnValue) const
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ return att->value;
+
+ return defaultReturnValue;
+}
+
+int XmlElement::getIntAttribute (StringRef attributeName, const int defaultReturnValue) const
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ return att->value.getIntValue();
+
+ return defaultReturnValue;
+}
+
+double XmlElement::getDoubleAttribute (StringRef attributeName, const double defaultReturnValue) const
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ return att->value.getDoubleValue();
+
+ return defaultReturnValue;
+}
+
+bool XmlElement::getBoolAttribute (StringRef attributeName, const bool defaultReturnValue) const
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ {
+ const juce_wchar firstChar = *(att->value.getCharPointer().findEndOfWhitespace());
+
+ return firstChar == '1'
+ || firstChar == 't'
+ || firstChar == 'y'
+ || firstChar == 'T'
+ || firstChar == 'Y';
+ }
+
+ return defaultReturnValue;
+}
+
+bool XmlElement::compareAttribute (StringRef attributeName,
+ StringRef stringToCompareAgainst,
+ const bool ignoreCase) const noexcept
+{
+ if (const XmlAttributeNode* att = getAttribute (attributeName))
+ return ignoreCase ? att->value.equalsIgnoreCase (stringToCompareAgainst)
+ : att->value == stringToCompareAgainst;
+
+ return false;
+}
+
+//==============================================================================
+void XmlElement::setAttribute (const Identifier& attributeName, const String& value)
+{
+ if (attributes == nullptr)
+ {
+ attributes = new XmlAttributeNode (attributeName, value);
+ }
+ else
+ {
+ for (XmlAttributeNode* att = attributes; ; att = att->nextListItem)
+ {
+ if (att->name == attributeName)
+ {
+ att->value = value;
+ break;
+ }
+
+ if (att->nextListItem == nullptr)
+ {
+ att->nextListItem = new XmlAttributeNode (attributeName, value);
+ break;
+ }
+ }
+ }
+}
+
+void XmlElement::setAttribute (const Identifier& attributeName, const int number)
+{
+ setAttribute (attributeName, String (number));
+}
+
+void XmlElement::setAttribute (const Identifier& attributeName, const double number)
+{
+ setAttribute (attributeName, String (number, 20));
+}
+
+void XmlElement::removeAttribute (const Identifier& attributeName) noexcept
+{
+ for (LinkedListPointer<XmlAttributeNode>* att = &attributes;
+ att->get() != nullptr;
+ att = &(att->get()->nextListItem))
+ {
+ if (att->get()->name == attributeName)
+ {
+ delete att->removeNext();
+ break;
+ }
+ }
+}
+
+void XmlElement::removeAllAttributes() noexcept
+{
+ attributes.deleteAll();
+}
+
+//==============================================================================
+int XmlElement::getNumChildElements() const noexcept
+{
+ return firstChildElement.size();
+}
+
+XmlElement* XmlElement::getChildElement (const int index) const noexcept
+{
+ return firstChildElement [index].get();
+}
+
+XmlElement* XmlElement::getChildByName (StringRef childName) const noexcept
+{
+ jassert (! childName.isEmpty());
+
+ for (XmlElement* child = firstChildElement; child != nullptr; child = child->nextListItem)
+ if (child->hasTagName (childName))
+ return child;
+
+ return nullptr;
+}
+
+XmlElement* XmlElement::getChildByAttribute (StringRef attributeName, StringRef attributeValue) const noexcept
+{
+ jassert (! attributeName.isEmpty());
+
+ for (XmlElement* child = firstChildElement; child != nullptr; child = child->nextListItem)
+ if (child->compareAttribute (attributeName, attributeValue))
+ return child;
+
+ return nullptr;
+}
+
+void XmlElement::addChildElement (XmlElement* const newNode) noexcept
+{
+ if (newNode != nullptr)
+ {
+ // The element being added must not be a child of another node!
+ jassert (newNode->nextListItem == nullptr);
+
+ firstChildElement.append (newNode);
+ }
+}
+
+void XmlElement::insertChildElement (XmlElement* const newNode, int indexToInsertAt) noexcept
+{
+ if (newNode != nullptr)
+ {
+ // The element being added must not be a child of another node!
+ jassert (newNode->nextListItem == nullptr);
+
+ firstChildElement.insertAtIndex (indexToInsertAt, newNode);
+ }
+}
+
+void XmlElement::prependChildElement (XmlElement* newNode) noexcept
+{
+ if (newNode != nullptr)
+ {
+ // The element being added must not be a child of another node!
+ jassert (newNode->nextListItem == nullptr);
+
+ firstChildElement.insertNext (newNode);
+ }
+}
+
+XmlElement* XmlElement::createNewChildElement (StringRef childTagName)
+{
+ XmlElement* const newElement = new XmlElement (childTagName);
+ addChildElement (newElement);
+ return newElement;
+}
+
+bool XmlElement::replaceChildElement (XmlElement* const currentChildElement,
+ XmlElement* const newNode) noexcept
+{
+ if (newNode != nullptr)
+ {
+ if (LinkedListPointer<XmlElement>* const p = firstChildElement.findPointerTo (currentChildElement))
+ {
+ if (currentChildElement != newNode)
+ delete p->replaceNext (newNode);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void XmlElement::removeChildElement (XmlElement* const childToRemove,
+ const bool shouldDeleteTheChild) noexcept
+{
+ if (childToRemove != nullptr)
+ {
+ firstChildElement.remove (childToRemove);
+
+ if (shouldDeleteTheChild)
+ delete childToRemove;
+ }
+}
+
+bool XmlElement::isEquivalentTo (const XmlElement* const other,
+ const bool ignoreOrderOfAttributes) const noexcept
+{
+ if (this != other)
+ {
+ if (other == nullptr || tagName != other->tagName)
+ return false;
+
+ if (ignoreOrderOfAttributes)
+ {
+ int totalAtts = 0;
+
+ for (const XmlAttributeNode* att = attributes; att != nullptr; att = att->nextListItem)
+ {
+ if (! other->compareAttribute (att->name, att->value))
+ return false;
+
+ ++totalAtts;
+ }
+
+ if (totalAtts != other->getNumAttributes())
+ return false;
+ }
+ else
+ {
+ const XmlAttributeNode* thisAtt = attributes;
+ const XmlAttributeNode* otherAtt = other->attributes;
+
+ for (;;)
+ {
+ if (thisAtt == nullptr || otherAtt == nullptr)
+ {
+ if (thisAtt == otherAtt) // both 0, so it's a match
+ break;
+
+ return false;
+ }
+
+ if (thisAtt->name != otherAtt->name
+ || thisAtt->value != otherAtt->value)
+ {
+ return false;
+ }
+
+ thisAtt = thisAtt->nextListItem;
+ otherAtt = otherAtt->nextListItem;
+ }
+ }
+
+ const XmlElement* thisChild = firstChildElement;
+ const XmlElement* otherChild = other->firstChildElement;
+
+ for (;;)
+ {
+ if (thisChild == nullptr || otherChild == nullptr)
+ {
+ if (thisChild == otherChild) // both 0, so it's a match
+ break;
+
+ return false;
+ }
+
+ if (! thisChild->isEquivalentTo (otherChild, ignoreOrderOfAttributes))
+ return false;
+
+ thisChild = thisChild->nextListItem;
+ otherChild = otherChild->nextListItem;
+ }
+ }
+
+ return true;
+}
+
+void XmlElement::deleteAllChildElements() noexcept
+{
+ firstChildElement.deleteAll();
+}
+
+void XmlElement::deleteAllChildElementsWithTagName (StringRef name) noexcept
+{
+ for (XmlElement* child = firstChildElement; child != nullptr;)
+ {
+ XmlElement* const nextChild = child->nextListItem;
+
+ if (child->hasTagName (name))
+ removeChildElement (child, true);
+
+ child = nextChild;
+ }
+}
+
+bool XmlElement::containsChildElement (const XmlElement* const possibleChild) const noexcept
+{
+ return firstChildElement.contains (possibleChild);
+}
+
+XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLookFor) noexcept
+{
+ if (this == elementToLookFor || elementToLookFor == nullptr)
+ return nullptr;
+
+ for (XmlElement* child = firstChildElement; child != nullptr; child = child->nextListItem)
+ {
+ if (elementToLookFor == child)
+ return this;
+
+ if (XmlElement* const found = child->findParentElementOf (elementToLookFor))
+ return found;
+ }
+
+ return nullptr;
+}
+
+void XmlElement::getChildElementsAsArray (XmlElement** elems) const noexcept
+{
+ firstChildElement.copyToArray (elems);
+}
+
+void XmlElement::reorderChildElements (XmlElement** const elems, const int num) noexcept
+{
+ XmlElement* e = firstChildElement = elems[0];
+
+ for (int i = 1; i < num; ++i)
+ {
+ e->nextListItem = elems[i];
+ e = e->nextListItem;
+ }
+
+ e->nextListItem = nullptr;
+}
+
+//==============================================================================
+bool XmlElement::isTextElement() const noexcept
+{
+ return tagName.isEmpty();
+}
+
+static const String juce_xmltextContentAttributeName ("text");
+
+const String& XmlElement::getText() const noexcept
+{
+ jassert (isTextElement()); // you're trying to get the text from an element that
+ // isn't actually a text element.. If this contains text sub-nodes, you
+ // probably want to use getAllSubText instead.
+
+ return getStringAttribute (juce_xmltextContentAttributeName);
+}
+
+void XmlElement::setText (const String& newText)
+{
+ if (isTextElement())
+ setAttribute (juce_xmltextContentAttributeName, newText);
+ else
+ jassertfalse; // you can only change the text in a text element, not a normal one.
+}
+
+String XmlElement::getAllSubText() const
+{
+ if (isTextElement())
+ return getText();
+
+ if (getNumChildElements() == 1)
+ return firstChildElement.get()->getAllSubText();
+
+ MemoryOutputStream mem (1024);
+
+ for (const XmlElement* child = firstChildElement; child != nullptr; child = child->nextListItem)
+ mem << child->getAllSubText();
+
+ return mem.toUTF8();
+}
+
+String XmlElement::getChildElementAllSubText (StringRef childTagName, const String& defaultReturnValue) const
+{
+ if (const XmlElement* const child = getChildByName (childTagName))
+ return child->getAllSubText();
+
+ return defaultReturnValue;
+}
+
+XmlElement* XmlElement::createTextElement (const String& text)
+{
+ XmlElement* const e = new XmlElement ((int) 0);
+ e->setAttribute (juce_xmltextContentAttributeName, text);
+ return e;
+}
+
+void XmlElement::addTextElement (const String& text)
+{
+ addChildElement (createTextElement (text));
+}
+
+void XmlElement::deleteAllTextElements() noexcept
+{
+ for (XmlElement* child = firstChildElement; child != nullptr;)
+ {
+ XmlElement* const next = child->nextListItem;
+
+ if (child->isTextElement())
+ removeChildElement (child, true);
+
+ child = next;
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.h b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.h
new file mode 100644
index 0000000..4ab4d08
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/xml/juce_XmlElement.h
@@ -0,0 +1,763 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_XMLELEMENT_H_INCLUDED
+#define JUCE_XMLELEMENT_H_INCLUDED
+
+
+//==============================================================================
+/** A handy macro to make it easy to iterate all the child elements in an XmlElement.
+
+ The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
+ will be the name of a pointer to each child element.
+
+ E.g. @code
+ XmlElement* myParentXml = createSomeKindOfXmlDocument();
+
+ forEachXmlChildElement (*myParentXml, child)
+ {
+ if (child->hasTagName ("FOO"))
+ doSomethingWithXmlElement (child);
+ }
+
+ @endcode
+
+ @see forEachXmlChildElementWithTagName
+*/
+#define forEachXmlChildElement(parentXmlElement, childElementVariableName) \
+\
+ for (juce::XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \
+ childElementVariableName != nullptr; \
+ childElementVariableName = childElementVariableName->getNextElement())
+
+/** A macro that makes it easy to iterate all the child elements of an XmlElement
+ which have a specified tag.
+
+ This does the same job as the forEachXmlChildElement macro, but only for those
+ elements that have a particular tag name.
+
+ The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
+ will be the name of a pointer to each child element. The requiredTagName is the
+ tag name to match.
+
+ E.g. @code
+ XmlElement* myParentXml = createSomeKindOfXmlDocument();
+
+ forEachXmlChildElementWithTagName (*myParentXml, child, "MYTAG")
+ {
+ // the child object is now guaranteed to be a <MYTAG> element..
+ doSomethingWithMYTAGElement (child);
+ }
+
+ @endcode
+
+ @see forEachXmlChildElement
+*/
+#define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
+\
+ for (juce::XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \
+ childElementVariableName != nullptr; \
+ childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName))
+
+
+//==============================================================================
+/** Used to build a tree of elements representing an XML document.
+
+ An XML document can be parsed into a tree of XmlElements, each of which
+ represents an XML tag structure, and which may itself contain other
+ nested elements.
+
+ An XmlElement can also be converted back into a text document, and has
+ lots of useful methods for manipulating its attributes and sub-elements,
+ so XmlElements can actually be used as a handy general-purpose data
+ structure.
+
+ Here's an example of parsing some elements: @code
+ // check we're looking at the right kind of document..
+ if (myElement->hasTagName ("ANIMALS"))
+ {
+ // now we'll iterate its sub-elements looking for 'giraffe' elements..
+ forEachXmlChildElement (*myElement, e)
+ {
+ if (e->hasTagName ("GIRAFFE"))
+ {
+ // found a giraffe, so use some of its attributes..
+
+ String giraffeName = e->getStringAttribute ("name");
+ int giraffeAge = e->getIntAttribute ("age");
+ bool isFriendly = e->getBoolAttribute ("friendly");
+ }
+ }
+ }
+ @endcode
+
+ And here's an example of how to create an XML document from scratch: @code
+ // create an outer node called "ANIMALS"
+ XmlElement animalsList ("ANIMALS");
+
+ for (int i = 0; i < numAnimals; ++i)
+ {
+ // create an inner element..
+ XmlElement* giraffe = new XmlElement ("GIRAFFE");
+
+ giraffe->setAttribute ("name", "nigel");
+ giraffe->setAttribute ("age", 10);
+ giraffe->setAttribute ("friendly", true);
+
+ // ..and add our new element to the parent node
+ animalsList.addChildElement (giraffe);
+ }
+
+ // now we can turn the whole thing into a text document..
+ String myXmlDoc = animalsList.createDocument (String::empty);
+ @endcode
+
+ @see XmlDocument
+*/
+class JUCE_API XmlElement
+{
+public:
+ //==============================================================================
+ /** Creates an XmlElement with this tag name. */
+ explicit XmlElement (const String& tagName);
+
+ /** Creates an XmlElement with this tag name. */
+ explicit XmlElement (const char* tagName);
+
+ /** Creates an XmlElement with this tag name. */
+ explicit XmlElement (const Identifier& tagName);
+
+ /** Creates an XmlElement with this tag name. */
+ explicit XmlElement (StringRef tagName);
+
+ /** Creates an XmlElement with this tag name. */
+ XmlElement (String::CharPointerType tagNameBegin, String::CharPointerType tagNameEnd);
+
+ /** Creates a (deep) copy of another element. */
+ XmlElement (const XmlElement&);
+
+ /** Creates a (deep) copy of another element. */
+ XmlElement& operator= (const XmlElement&);
+
+ #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ XmlElement (XmlElement&&) noexcept;
+ XmlElement& operator= (XmlElement&&) noexcept;
+ #endif
+
+ /** Deleting an XmlElement will also delete all of its child elements. */
+ ~XmlElement() noexcept;
+
+ //==============================================================================
+ /** Compares two XmlElements to see if they contain the same text and attiributes.
+
+ The elements are only considered equivalent if they contain the same attiributes
+ with the same values, and have the same sub-nodes.
+
+ @param other the other element to compare to
+ @param ignoreOrderOfAttributes if true, this means that two elements with the
+ same attributes in a different order will be
+ considered the same; if false, the attributes must
+ be in the same order as well
+ */
+ bool isEquivalentTo (const XmlElement* other,
+ bool ignoreOrderOfAttributes) const noexcept;
+
+ //==============================================================================
+ /** Returns an XML text document that represents this element.
+
+ The string returned can be parsed to recreate the same XmlElement that
+ was used to create it.
+
+ @param dtdToUse the DTD to add to the document
+ @param allOnOneLine if true, this means that the document will not contain any
+ linefeeds, so it'll be smaller but not very easy to read.
+ @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
+ document
+ @param encodingType the character encoding format string to put into the xml
+ header
+ @param lineWrapLength the line length that will be used before items get placed on
+ a new line. This isn't an absolute maximum length, it just
+ determines how lists of attributes get broken up
+ @see writeToStream, writeToFile
+ */
+ String createDocument (StringRef dtdToUse,
+ bool allOnOneLine = false,
+ bool includeXmlHeader = true,
+ StringRef encodingType = "UTF-8",
+ int lineWrapLength = 60) const;
+
+ /** Writes the document to a stream as UTF-8.
+
+ @param output the stream to write to
+ @param dtdToUse the DTD to add to the document
+ @param allOnOneLine if true, this means that the document will not contain any
+ linefeeds, so it'll be smaller but not very easy to read.
+ @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
+ document
+ @param encodingType the character encoding format string to put into the xml
+ header
+ @param lineWrapLength the line length that will be used before items get placed on
+ a new line. This isn't an absolute maximum length, it just
+ determines how lists of attributes get broken up
+ @see writeToFile, createDocument
+ */
+ void writeToStream (OutputStream& output,
+ StringRef dtdToUse,
+ bool allOnOneLine = false,
+ bool includeXmlHeader = true,
+ StringRef encodingType = "UTF-8",
+ int lineWrapLength = 60) const;
+
+ /** Writes the element to a file as an XML document.
+
+ To improve safety in case something goes wrong while writing the file, this
+ will actually write the document to a new temporary file in the same
+ directory as the destination file, and if this succeeds, it will rename this
+ new file as the destination file (overwriting any existing file that was there).
+
+ @param destinationFile the file to write to. If this already exists, it will be
+ overwritten.
+ @param dtdToUse the DTD to add to the document
+ @param encodingType the character encoding format string to put into the xml
+ header
+ @param lineWrapLength the line length that will be used before items get placed on
+ a new line. This isn't an absolute maximum length, it just
+ determines how lists of attributes get broken up
+ @returns true if the file is written successfully; false if something goes wrong
+ in the process
+ @see createDocument
+ */
+ bool writeToFile (const File& destinationFile,
+ StringRef dtdToUse,
+ StringRef encodingType = "UTF-8",
+ int lineWrapLength = 60) const;
+
+ //==============================================================================
+ /** Returns this element's tag type name.
+ E.g. for an element such as \<MOOSE legs="4" antlers="2">, this would return "MOOSE".
+ @see hasTagName
+ */
+ const String& getTagName() const noexcept { return tagName; }
+
+ /** Returns the namespace portion of the tag-name, or an empty string if none is specified. */
+ String getNamespace() const;
+
+ /** Returns the part of the tag-name that follows any namespace declaration. */
+ String getTagNameWithoutNamespace() const;
+
+ /** Tests whether this element has a particular tag name.
+ @param possibleTagName the tag name you're comparing it with
+ @see getTagName
+ */
+ bool hasTagName (StringRef possibleTagName) const noexcept;
+
+ /** Tests whether this element has a particular tag name, ignoring any XML namespace prefix.
+ So a test for e.g. "xyz" will return true for "xyz" and also "foo:xyz", "bar::xyz", etc.
+ @see getTagName
+ */
+ bool hasTagNameIgnoringNamespace (StringRef possibleTagName) const;
+
+ //==============================================================================
+ /** Returns the number of XML attributes this element contains.
+
+ E.g. for an element such as \<MOOSE legs="4" antlers="2">, this would
+ return 2.
+ */
+ int getNumAttributes() const noexcept;
+
+ /** Returns the name of one of the elements attributes.
+
+ E.g. for an element such as \<MOOSE legs="4" antlers="2">, then
+ getAttributeName(1) would return "antlers".
+
+ @see getAttributeValue, getStringAttribute
+ */
+ const String& getAttributeName (int attributeIndex) const noexcept;
+
+ /** Returns the value of one of the elements attributes.
+
+ E.g. for an element such as \<MOOSE legs="4" antlers="2">, then
+ getAttributeName(1) would return "2".
+
+ @see getAttributeName, getStringAttribute
+ */
+ const String& getAttributeValue (int attributeIndex) const noexcept;
+
+ //==============================================================================
+ // Attribute-handling methods..
+
+ /** Checks whether the element contains an attribute with a certain name. */
+ bool hasAttribute (StringRef attributeName) const noexcept;
+
+ /** Returns the value of a named attribute.
+ @param attributeName the name of the attribute to look up
+ */
+ const String& getStringAttribute (StringRef attributeName) const noexcept;
+
+ /** Returns the value of a named attribute.
+ @param attributeName the name of the attribute to look up
+ @param defaultReturnValue a value to return if the element doesn't have an attribute
+ with this name
+ */
+ String getStringAttribute (StringRef attributeName, const String& defaultReturnValue) const;
+
+ /** Compares the value of a named attribute with a value passed-in.
+
+ @param attributeName the name of the attribute to look up
+ @param stringToCompareAgainst the value to compare it with
+ @param ignoreCase whether the comparison should be case-insensitive
+ @returns true if the value of the attribute is the same as the string passed-in;
+ false if it's different (or if no such attribute exists)
+ */
+ bool compareAttribute (StringRef attributeName,
+ StringRef stringToCompareAgainst,
+ bool ignoreCase = false) const noexcept;
+
+ /** Returns the value of a named attribute as an integer.
+
+ This will try to find the attribute and convert it to an integer (using
+ the String::getIntValue() method).
+
+ @param attributeName the name of the attribute to look up
+ @param defaultReturnValue a value to return if the element doesn't have an attribute
+ with this name
+ @see setAttribute
+ */
+ int getIntAttribute (StringRef attributeName, int defaultReturnValue = 0) const;
+
+ /** Returns the value of a named attribute as floating-point.
+
+ This will try to find the attribute and convert it to an integer (using
+ the String::getDoubleValue() method).
+
+ @param attributeName the name of the attribute to look up
+ @param defaultReturnValue a value to return if the element doesn't have an attribute
+ with this name
+ @see setAttribute
+ */
+ double getDoubleAttribute (StringRef attributeName, double defaultReturnValue = 0.0) const;
+
+ /** Returns the value of a named attribute as a boolean.
+
+ This will try to find the attribute and interpret it as a boolean. To do this,
+ it'll return true if the value is "1", "true", "y", etc, or false for other
+ values.
+
+ @param attributeName the name of the attribute to look up
+ @param defaultReturnValue a value to return if the element doesn't have an attribute
+ with this name
+ */
+ bool getBoolAttribute (StringRef attributeName, bool defaultReturnValue = false) const;
+
+ /** Adds a named attribute to the element.
+
+ If the element already contains an attribute with this name, it's value will
+ be updated to the new value. If there's no such attribute yet, a new one will
+ be added.
+
+ Note that there are other setAttribute() methods that take integers,
+ doubles, etc. to make it easy to store numbers.
+
+ @param attributeName the name of the attribute to set
+ @param newValue the value to set it to
+ @see removeAttribute
+ */
+ void setAttribute (const Identifier& attributeName, const String& newValue);
+
+ /** Adds a named attribute to the element, setting it to an integer value.
+
+ If the element already contains an attribute with this name, it's value will
+ be updated to the new value. If there's no such attribute yet, a new one will
+ be added.
+
+ Note that there are other setAttribute() methods that take integers,
+ doubles, etc. to make it easy to store numbers.
+
+ @param attributeName the name of the attribute to set
+ @param newValue the value to set it to
+ */
+ void setAttribute (const Identifier& attributeName, int newValue);
+
+ /** Adds a named attribute to the element, setting it to a floating-point value.
+
+ If the element already contains an attribute with this name, it's value will
+ be updated to the new value. If there's no such attribute yet, a new one will
+ be added.
+
+ Note that there are other setAttribute() methods that take integers,
+ doubles, etc. to make it easy to store numbers.
+
+ @param attributeName the name of the attribute to set
+ @param newValue the value to set it to
+ */
+ void setAttribute (const Identifier& attributeName, double newValue);
+
+ /** Removes a named attribute from the element.
+
+ @param attributeName the name of the attribute to remove
+ @see removeAllAttributes
+ */
+ void removeAttribute (const Identifier& attributeName) noexcept;
+
+ /** Removes all attributes from this element. */
+ void removeAllAttributes() noexcept;
+
+ //==============================================================================
+ // Child element methods..
+
+ /** Returns the first of this element's sub-elements.
+ see getNextElement() for an example of how to iterate the sub-elements.
+ @see forEachXmlChildElement
+ */
+ XmlElement* getFirstChildElement() const noexcept { return firstChildElement; }
+
+ /** Returns the next of this element's siblings.
+
+ This can be used for iterating an element's sub-elements, e.g.
+ @code
+ XmlElement* child = myXmlDocument->getFirstChildElement();
+
+ while (child != nullptr)
+ {
+ ...do stuff with this child..
+
+ child = child->getNextElement();
+ }
+ @endcode
+
+ Note that when iterating the child elements, some of them might be
+ text elements as well as XML tags - use isTextElement() to work this
+ out.
+
+ Also, it's much easier and neater to use this method indirectly via the
+ forEachXmlChildElement macro.
+
+ @returns the sibling element that follows this one, or zero if this is the last
+ element in its parent
+
+ @see getNextElement, isTextElement, forEachXmlChildElement
+ */
+ inline XmlElement* getNextElement() const noexcept { return nextListItem; }
+
+ /** Returns the next of this element's siblings which has the specified tag
+ name.
+
+ This is like getNextElement(), but will scan through the list until it
+ finds an element with the given tag name.
+
+ @see getNextElement, forEachXmlChildElementWithTagName
+ */
+ XmlElement* getNextElementWithTagName (StringRef requiredTagName) const;
+
+ /** Returns the number of sub-elements in this element.
+ @see getChildElement
+ */
+ int getNumChildElements() const noexcept;
+
+ /** Returns the sub-element at a certain index.
+
+ It's not very efficient to iterate the sub-elements by index - see
+ getNextElement() for an example of how best to iterate.
+
+ @returns the n'th child of this element, or nullptr if the index is out-of-range
+ @see getNextElement, isTextElement, getChildByName
+ */
+ XmlElement* getChildElement (int index) const noexcept;
+
+ /** Returns the first sub-element with a given tag-name.
+
+ @param tagNameToLookFor the tag name of the element you want to find
+ @returns the first element with this tag name, or nullptr if none is found
+ @see getNextElement, isTextElement, getChildElement, getChildByAttribute
+ */
+ XmlElement* getChildByName (StringRef tagNameToLookFor) const noexcept;
+
+ /** Returns the first sub-element which has an attribute that matches the given value.
+
+ @param attributeName the name of the attribute to check
+ @param attributeValue the target value of the attribute
+ @returns the first element with this attribute value, or nullptr if none is found
+ @see getChildByName
+ */
+ XmlElement* getChildByAttribute (StringRef attributeName,
+ StringRef attributeValue) const noexcept;
+
+ //==============================================================================
+ /** Appends an element to this element's list of children.
+
+ Child elements are deleted automatically when their parent is deleted, so
+ make sure the object that you pass in will not be deleted by anything else,
+ and make sure it's not already the child of another element.
+
+ Note that due to the XmlElement using a singly-linked-list, prependChildElement()
+ is an O(1) operation, but addChildElement() is an O(N) operation - so if
+ you're adding large number of elements, you may prefer to do so in reverse order!
+
+ @see getFirstChildElement, getNextElement, getNumChildElements,
+ getChildElement, removeChildElement
+ */
+ void addChildElement (XmlElement* newChildElement) noexcept;
+
+ /** Inserts an element into this element's list of children.
+
+ Child elements are deleted automatically when their parent is deleted, so
+ make sure the object that you pass in will not be deleted by anything else,
+ and make sure it's not already the child of another element.
+
+ @param newChildElement the element to add
+ @param indexToInsertAt the index at which to insert the new element - if this is
+ below zero, it will be added to the end of the list
+ @see addChildElement, insertChildElement
+ */
+ void insertChildElement (XmlElement* newChildElement,
+ int indexToInsertAt) noexcept;
+
+ /** Inserts an element at the beginning of this element's list of children.
+
+ Child elements are deleted automatically when their parent is deleted, so
+ make sure the object that you pass in will not be deleted by anything else,
+ and make sure it's not already the child of another element.
+
+ Note that due to the XmlElement using a singly-linked-list, prependChildElement()
+ is an O(1) operation, but addChildElement() is an O(N) operation - so if
+ you're adding large number of elements, you may prefer to do so in reverse order!
+
+ @see addChildElement, insertChildElement
+ */
+ void prependChildElement (XmlElement* newChildElement) noexcept;
+
+ /** Creates a new element with the given name and returns it, after adding it
+ as a child element.
+
+ This is a handy method that means that instead of writing this:
+ @code
+ XmlElement* newElement = new XmlElement ("foobar");
+ myParentElement->addChildElement (newElement);
+ @endcode
+
+ ..you could just write this:
+ @code
+ XmlElement* newElement = myParentElement->createNewChildElement ("foobar");
+ @endcode
+ */
+ XmlElement* createNewChildElement (StringRef tagName);
+
+ /** Replaces one of this element's children with another node.
+
+ If the current element passed-in isn't actually a child of this element,
+ this will return false and the new one won't be added. Otherwise, the
+ existing element will be deleted, replaced with the new one, and it
+ will return true.
+ */
+ bool replaceChildElement (XmlElement* currentChildElement,
+ XmlElement* newChildNode) noexcept;
+
+ /** Removes a child element.
+
+ @param childToRemove the child to look for and remove
+ @param shouldDeleteTheChild if true, the child will be deleted, if false it'll
+ just remove it
+ */
+ void removeChildElement (XmlElement* childToRemove,
+ bool shouldDeleteTheChild) noexcept;
+
+ /** Deletes all the child elements in the element.
+ @see removeChildElement, deleteAllChildElementsWithTagName
+ */
+ void deleteAllChildElements() noexcept;
+
+ /** Deletes all the child elements with a given tag name.
+ @see removeChildElement
+ */
+ void deleteAllChildElementsWithTagName (StringRef tagName) noexcept;
+
+ /** Returns true if the given element is a child of this one. */
+ bool containsChildElement (const XmlElement* possibleChild) const noexcept;
+
+ /** Recursively searches all sub-elements to find one that contains the specified
+ child element.
+ */
+ XmlElement* findParentElementOf (const XmlElement* elementToLookFor) noexcept;
+
+ //==============================================================================
+ /** Sorts the child elements using a comparator.
+
+ This will use a comparator object to sort the elements into order. The object
+ passed must have a method of the form:
+ @code
+ int compareElements (const XmlElement* first, const XmlElement* second);
+ @endcode
+
+ ..and this method must return:
+ - a value of < 0 if the first comes before the second
+ - a value of 0 if the two objects are equivalent
+ - a value of > 0 if the second comes before the first
+
+ To improve performance, the compareElements() method can be declared as static or const.
+
+ @param comparator the comparator to use for comparing elements.
+ @param retainOrderOfEquivalentItems if this is true, then items which the comparator
+ says are equivalent will be kept in the order in which they
+ currently appear in the array. This is slower to perform, but
+ may be important in some cases. If it's false, a faster algorithm
+ is used, but equivalent elements may be rearranged.
+ */
+ template <class ElementComparator>
+ void sortChildElements (ElementComparator& comparator,
+ bool retainOrderOfEquivalentItems = false)
+ {
+ const int num = getNumChildElements();
+
+ if (num > 1)
+ {
+ HeapBlock <XmlElement*> elems ((size_t) num);
+ getChildElementsAsArray (elems);
+ sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems);
+ reorderChildElements (elems, num);
+ }
+ }
+
+ //==============================================================================
+ /** Returns true if this element is a section of text.
+
+ Elements can either be an XML tag element or a secton of text, so this
+ is used to find out what kind of element this one is.
+
+ @see getAllText, addTextElement, deleteAllTextElements
+ */
+ bool isTextElement() const noexcept;
+
+ /** Returns the text for a text element.
+
+ Note that if you have an element like this:
+
+ @code<xyz>hello</xyz>@endcode
+
+ then calling getText on the "xyz" element won't return "hello", because that is
+ actually stored in a special text sub-element inside the xyz element. To get the
+ "hello" string, you could either call getText on the (unnamed) sub-element, or
+ use getAllSubText() to do this automatically.
+
+ Note that leading and trailing whitespace will be included in the string - to remove
+ if, just call String::trim() on the result.
+
+ @see isTextElement, getAllSubText, getChildElementAllSubText
+ */
+ const String& getText() const noexcept;
+
+ /** Sets the text in a text element.
+
+ Note that this is only a valid call if this element is a text element. If it's
+ not, then no action will be performed. If you're trying to add text inside a normal
+ element, you probably want to use addTextElement() instead.
+ */
+ void setText (const String& newText);
+
+ /** Returns all the text from this element's child nodes.
+
+ This iterates all the child elements and when it finds text elements,
+ it concatenates their text into a big string which it returns.
+
+ E.g. @code<xyz>hello <x>there</x> world</xyz>@endcode
+ if you called getAllSubText on the "xyz" element, it'd return "hello there world".
+
+ Note that leading and trailing whitespace will be included in the string - to remove
+ if, just call String::trim() on the result.
+
+ @see isTextElement, getChildElementAllSubText, getText, addTextElement
+ */
+ String getAllSubText() const;
+
+ /** Returns all the sub-text of a named child element.
+
+ If there is a child element with the given tag name, this will return
+ all of its sub-text (by calling getAllSubText() on it). If there is
+ no such child element, this will return the default string passed-in.
+
+ @see getAllSubText
+ */
+ String getChildElementAllSubText (StringRef childTagName,
+ const String& defaultReturnValue) const;
+
+ /** Appends a section of text to this element.
+ @see isTextElement, getText, getAllSubText
+ */
+ void addTextElement (const String& text);
+
+ /** Removes all the text elements from this element.
+ @see isTextElement, getText, getAllSubText, addTextElement
+ */
+ void deleteAllTextElements() noexcept;
+
+ /** Creates a text element that can be added to a parent element. */
+ static XmlElement* createTextElement (const String& text);
+
+ //==============================================================================
+private:
+ struct XmlAttributeNode
+ {
+ XmlAttributeNode (const XmlAttributeNode&) noexcept;
+ XmlAttributeNode (const Identifier&, const String&) noexcept;
+ XmlAttributeNode (String::CharPointerType, String::CharPointerType);
+
+ LinkedListPointer<XmlAttributeNode> nextListItem;
+ Identifier name;
+ String value;
+
+ private:
+ XmlAttributeNode& operator= (const XmlAttributeNode&) JUCE_DELETED_FUNCTION;
+ };
+
+ friend class XmlDocument;
+ friend class LinkedListPointer<XmlAttributeNode>;
+ friend class LinkedListPointer<XmlElement>;
+ friend class LinkedListPointer<XmlElement>::Appender;
+ friend class NamedValueSet;
+
+ LinkedListPointer<XmlElement> nextListItem;
+ LinkedListPointer<XmlElement> firstChildElement;
+ LinkedListPointer<XmlAttributeNode> attributes;
+ String tagName;
+
+ XmlElement (int) noexcept;
+ void copyChildrenAndAttributesFrom (const XmlElement&);
+ void writeElementAsText (OutputStream&, int indentationLevel, int lineWrapLength) const;
+ void getChildElementsAsArray (XmlElement**) const noexcept;
+ void reorderChildElements (XmlElement**, int) noexcept;
+ XmlAttributeNode* getAttribute (StringRef) const noexcept;
+
+ // Sigh.. L"" or _T("") string literals are problematic in general, and really inappropriate
+ // for XML tags. Use a UTF-8 encoded literal instead, or if you're really determined to use
+ // UTF-16, cast it to a String and use the other constructor.
+ XmlElement (const wchar_t*) JUCE_DELETED_FUNCTION;
+
+ JUCE_LEAK_DETECTOR (XmlElement)
+};
+
+
+#endif // JUCE_XMLELEMENT_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp
new file mode 100644
index 0000000..cb9a577
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp
@@ -0,0 +1,213 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class GZIPCompressorOutputStream::GZIPCompressorHelper
+{
+public:
+ GZIPCompressorHelper (const int compressionLevel, const int windowBits)
+ : compLevel ((compressionLevel < 1 || compressionLevel > 9) ? -1 : compressionLevel),
+ isFirstDeflate (true),
+ streamIsValid (false),
+ finished (false)
+ {
+ using namespace zlibNamespace;
+ zerostruct (stream);
+
+ streamIsValid = (deflateInit2 (&stream, compLevel, Z_DEFLATED,
+ windowBits != 0 ? windowBits : MAX_WBITS,
+ 8, strategy) == Z_OK);
+ }
+
+ ~GZIPCompressorHelper()
+ {
+ if (streamIsValid)
+ zlibNamespace::deflateEnd (&stream);
+ }
+
+ bool write (const uint8* data, size_t dataSize, OutputStream& out)
+ {
+ // When you call flush() on a gzip stream, the stream is closed, and you can
+ // no longer continue to write data to it!
+ jassert (! finished);
+
+ while (dataSize > 0)
+ if (! doNextBlock (data, dataSize, out, Z_NO_FLUSH))
+ return false;
+
+ return true;
+ }
+
+ void finish (OutputStream& out)
+ {
+ const uint8* data = nullptr;
+ size_t dataSize = 0;
+
+ while (! finished)
+ doNextBlock (data, dataSize, out, Z_FINISH);
+ }
+
+private:
+ enum { strategy = 0 };
+
+ zlibNamespace::z_stream stream;
+ const int compLevel;
+ bool isFirstDeflate, streamIsValid, finished;
+ zlibNamespace::Bytef buffer[32768];
+
+ bool doNextBlock (const uint8*& data, size_t& dataSize, OutputStream& out, const int flushMode)
+ {
+ using namespace zlibNamespace;
+
+ if (streamIsValid)
+ {
+ stream.next_in = const_cast <uint8*> (data);
+ stream.next_out = buffer;
+ stream.avail_in = (z_uInt) dataSize;
+ stream.avail_out = (z_uInt) sizeof (buffer);
+
+ const int result = isFirstDeflate ? deflateParams (&stream, compLevel, strategy)
+ : deflate (&stream, flushMode);
+ isFirstDeflate = false;
+
+ switch (result)
+ {
+ case Z_STREAM_END:
+ finished = true;
+ // Deliberate fall-through..
+ case Z_OK:
+ {
+ data += dataSize - stream.avail_in;
+ dataSize = stream.avail_in;
+ const ssize_t bytesDone = (ssize_t) sizeof (buffer) - (ssize_t) stream.avail_out;
+ return bytesDone <= 0 || out.write (buffer, (size_t) bytesDone);
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ JUCE_DECLARE_NON_COPYABLE (GZIPCompressorHelper)
+};
+
+//==============================================================================
+GZIPCompressorOutputStream::GZIPCompressorOutputStream (OutputStream* const out,
+ const int compressionLevel,
+ const bool deleteDestStream,
+ const int windowBits)
+ : destStream (out, deleteDestStream),
+ helper (new GZIPCompressorHelper (compressionLevel, windowBits))
+{
+ jassert (out != nullptr);
+}
+
+GZIPCompressorOutputStream::~GZIPCompressorOutputStream()
+{
+ flush();
+}
+
+void GZIPCompressorOutputStream::flush()
+{
+ helper->finish (*destStream);
+ destStream->flush();
+}
+
+bool GZIPCompressorOutputStream::write (const void* destBuffer, size_t howMany)
+{
+ jassert (destBuffer != nullptr && (ssize_t) howMany >= 0);
+
+ return helper->write (static_cast <const uint8*> (destBuffer), howMany, *destStream);
+}
+
+int64 GZIPCompressorOutputStream::getPosition()
+{
+ return destStream->getPosition();
+}
+
+bool GZIPCompressorOutputStream::setPosition (int64 /*newPosition*/)
+{
+ jassertfalse; // can't do it!
+ return false;
+}
+
+//==============================================================================
+#if JUCE_UNIT_TESTS
+
+class GZIPTests : public UnitTest
+{
+public:
+ GZIPTests() : UnitTest ("GZIP") {}
+
+ void runTest()
+ {
+ beginTest ("GZIP");
+ Random rng = getRandom();
+
+ for (int i = 100; --i >= 0;)
+ {
+ MemoryOutputStream original, compressed, uncompressed;
+
+ {
+ GZIPCompressorOutputStream zipper (&compressed, rng.nextInt (10), false);
+
+ for (int j = rng.nextInt (100); --j >= 0;)
+ {
+ MemoryBlock data ((unsigned int) (rng.nextInt (2000) + 1));
+
+ for (int k = (int) data.getSize(); --k >= 0;)
+ data[k] = (char) rng.nextInt (255);
+
+ original << data;
+ zipper << data;
+ }
+ }
+
+ {
+ MemoryInputStream compressedInput (compressed.getData(), compressed.getDataSize(), false);
+ GZIPDecompressorInputStream unzipper (compressedInput);
+
+ uncompressed << unzipper;
+ }
+
+ expectEquals ((int) uncompressed.getDataSize(),
+ (int) original.getDataSize());
+
+ if (original.getDataSize() == uncompressed.getDataSize())
+ expect (memcmp (uncompressed.getData(),
+ original.getData(),
+ original.getDataSize()) == 0);
+ }
+ }
+};
+
+static GZIPTests gzipTests;
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h
new file mode 100644
index 0000000..3309486
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h
@@ -0,0 +1,101 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_GZIPCOMPRESSOROUTPUTSTREAM_H_INCLUDED
+#define JUCE_GZIPCOMPRESSOROUTPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ A stream which uses zlib to compress the data written into it.
+
+ Important note: When you call flush() on a GZIPCompressorOutputStream,
+ the gzip data is closed - this means that no more data can be written to
+ it, and any subsequent attempts to call write() will cause an assertion.
+
+ @see GZIPDecompressorInputStream
+*/
+class JUCE_API GZIPCompressorOutputStream : public OutputStream
+{
+public:
+ //==============================================================================
+ /** Creates a compression stream.
+
+ @param destStream the stream into which the compressed data should
+ be written
+ @param compressionLevel how much to compress the data, between 1 and 9, where
+ 1 is the fastest/lowest compression, and 9 is the
+ slowest/highest compression. Any value outside this range
+ indicates that a default compression level should be used.
+ @param deleteDestStreamWhenDestroyed whether or not to delete the destStream object when
+ this stream is destroyed
+ @param windowBits this is used internally to change the window size used
+ by zlib - leave it as 0 unless you specifically need to set
+ its value for some reason
+ */
+ GZIPCompressorOutputStream (OutputStream* destStream,
+ int compressionLevel = 0,
+ bool deleteDestStreamWhenDestroyed = false,
+ int windowBits = 0);
+
+ /** Destructor. */
+ ~GZIPCompressorOutputStream();
+
+ //==============================================================================
+ /** Flushes and closes the stream.
+ Note that unlike most streams, when you call flush() on a GZIPCompressorOutputStream,
+ the stream is closed - this means that no more data can be written to it, and any
+ subsequent attempts to call write() will cause an assertion.
+ */
+ void flush();
+
+ int64 getPosition() override;
+ bool setPosition (int64) override;
+ bool write (const void*, size_t) override;
+
+ /** These are preset values that can be used for the constructor's windowBits parameter.
+ For more info about this, see the zlib documentation for its windowBits parameter.
+ */
+ enum WindowBitsValues
+ {
+ windowBitsRaw = -15,
+ windowBitsGZIP = 15 + 16
+ };
+
+private:
+ //==============================================================================
+ OptionalScopedPointer<OutputStream> destStream;
+
+ class GZIPCompressorHelper;
+ friend struct ContainerDeletePolicy<GZIPCompressorHelper>;
+ ScopedPointer<GZIPCompressorHelper> helper;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GZIPCompressorOutputStream)
+};
+
+#endif // JUCE_GZIPCOMPRESSOROUTPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp
new file mode 100644
index 0000000..71e0850
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp
@@ -0,0 +1,288 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#if JUCE_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4309 4305 4365)
+#endif
+
+namespace zlibNamespace
+{
+ #if JUCE_INCLUDE_ZLIB_CODE
+ #if JUCE_CLANG
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wconversion"
+ #pragma clang diagnostic ignored "-Wshadow"
+ #pragma clang diagnostic ignored "-Wdeprecated-register"
+ #endif
+
+ #undef OS_CODE
+ #undef fdopen
+ #define ZLIB_INTERNAL
+ #define NO_DUMMY_DECL
+ #include "zlib/zlib.h"
+ #include "zlib/adler32.c"
+ #include "zlib/compress.c"
+ #undef DO1
+ #undef DO8
+ #include "zlib/crc32.c"
+ #include "zlib/deflate.c"
+ #include "zlib/inffast.c"
+ #undef PULLBYTE
+ #undef LOAD
+ #undef RESTORE
+ #undef INITBITS
+ #undef NEEDBITS
+ #undef DROPBITS
+ #undef BYTEBITS
+ #include "zlib/inflate.c"
+ #include "zlib/inftrees.c"
+ #include "zlib/trees.c"
+ #include "zlib/zutil.c"
+ #undef Byte
+ #undef fdopen
+ #undef local
+ #undef Freq
+ #undef Code
+ #undef Dad
+ #undef Len
+
+ #if JUCE_CLANG
+ #pragma clang diagnostic pop
+ #endif
+ #else
+ #include JUCE_ZLIB_INCLUDE_PATH
+ #endif
+}
+
+#if JUCE_MSVC
+ #pragma warning (pop)
+#endif
+
+//==============================================================================
+// internal helper object that holds the zlib structures so they don't have to be
+// included publicly.
+class GZIPDecompressorInputStream::GZIPDecompressHelper
+{
+public:
+ GZIPDecompressHelper (const bool dontWrap)
+ : finished (true),
+ needsDictionary (false),
+ error (true),
+ streamIsValid (false),
+ data (nullptr),
+ dataSize (0)
+ {
+ using namespace zlibNamespace;
+ zerostruct (stream);
+ streamIsValid = (inflateInit2 (&stream, dontWrap ? -MAX_WBITS : MAX_WBITS) == Z_OK);
+ finished = error = ! streamIsValid;
+ }
+
+ ~GZIPDecompressHelper()
+ {
+ using namespace zlibNamespace;
+ if (streamIsValid)
+ inflateEnd (&stream);
+ }
+
+ bool needsInput() const noexcept { return dataSize <= 0; }
+
+ void setInput (uint8* const data_, const size_t size) noexcept
+ {
+ data = data_;
+ dataSize = size;
+ }
+
+ int doNextBlock (uint8* const dest, const unsigned int destSize)
+ {
+ using namespace zlibNamespace;
+ if (streamIsValid && data != nullptr && ! finished)
+ {
+ stream.next_in = data;
+ stream.next_out = dest;
+ stream.avail_in = (z_uInt) dataSize;
+ stream.avail_out = (z_uInt) destSize;
+
+ switch (inflate (&stream, Z_PARTIAL_FLUSH))
+ {
+ case Z_STREAM_END:
+ finished = true;
+ // deliberate fall-through
+ case Z_OK:
+ data += dataSize - stream.avail_in;
+ dataSize = (z_uInt) stream.avail_in;
+ return (int) (destSize - stream.avail_out);
+
+ case Z_NEED_DICT:
+ needsDictionary = true;
+ data += dataSize - stream.avail_in;
+ dataSize = (size_t) stream.avail_in;
+ break;
+
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ error = true;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+ }
+
+ bool finished, needsDictionary, error, streamIsValid;
+
+ enum { gzipDecompBufferSize = 32768 };
+
+private:
+ zlibNamespace::z_stream stream;
+ uint8* data;
+ size_t dataSize;
+
+ JUCE_DECLARE_NON_COPYABLE (GZIPDecompressHelper)
+};
+
+//==============================================================================
+GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const source,
+ const bool deleteSourceWhenDestroyed,
+ const bool noWrap_,
+ const int64 uncompressedStreamLength_)
+ : sourceStream (source, deleteSourceWhenDestroyed),
+ uncompressedStreamLength (uncompressedStreamLength_),
+ noWrap (noWrap_),
+ isEof (false),
+ activeBufferSize (0),
+ originalSourcePos (source->getPosition()),
+ currentPos (0),
+ buffer ((size_t) GZIPDecompressHelper::gzipDecompBufferSize),
+ helper (new GZIPDecompressHelper (noWrap_))
+{
+}
+
+GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream& source)
+ : sourceStream (&source, false),
+ uncompressedStreamLength (-1),
+ noWrap (false),
+ isEof (false),
+ activeBufferSize (0),
+ originalSourcePos (source.getPosition()),
+ currentPos (0),
+ buffer ((size_t) GZIPDecompressHelper::gzipDecompBufferSize),
+ helper (new GZIPDecompressHelper (false))
+{
+}
+
+GZIPDecompressorInputStream::~GZIPDecompressorInputStream()
+{
+}
+
+int64 GZIPDecompressorInputStream::getTotalLength()
+{
+ return uncompressedStreamLength;
+}
+
+int GZIPDecompressorInputStream::read (void* destBuffer, int howMany)
+{
+ jassert (destBuffer != nullptr && howMany >= 0);
+
+ if (howMany > 0 && ! isEof)
+ {
+ int numRead = 0;
+ uint8* d = static_cast <uint8*> (destBuffer);
+
+ while (! helper->error)
+ {
+ const int n = helper->doNextBlock (d, (unsigned int) howMany);
+ currentPos += n;
+
+ if (n == 0)
+ {
+ if (helper->finished || helper->needsDictionary)
+ {
+ isEof = true;
+ return numRead;
+ }
+
+ if (helper->needsInput())
+ {
+ activeBufferSize = sourceStream->read (buffer, (int) GZIPDecompressHelper::gzipDecompBufferSize);
+
+ if (activeBufferSize > 0)
+ {
+ helper->setInput (buffer, (size_t) activeBufferSize);
+ }
+ else
+ {
+ isEof = true;
+ return numRead;
+ }
+ }
+ }
+ else
+ {
+ numRead += n;
+ howMany -= n;
+ d += n;
+
+ if (howMany <= 0)
+ return numRead;
+ }
+ }
+ }
+
+ return 0;
+}
+
+bool GZIPDecompressorInputStream::isExhausted()
+{
+ return helper->error || isEof;
+}
+
+int64 GZIPDecompressorInputStream::getPosition()
+{
+ return currentPos;
+}
+
+bool GZIPDecompressorInputStream::setPosition (int64 newPos)
+{
+ if (newPos < currentPos)
+ {
+ // to go backwards, reset the stream and start again..
+ isEof = false;
+ activeBufferSize = 0;
+ currentPos = 0;
+ helper = new GZIPDecompressHelper (noWrap);
+
+ sourceStream->setPosition (originalSourcePos);
+ }
+
+ skipNextBytes (newPos - currentPos);
+ return true;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h
new file mode 100644
index 0000000..78a0b77
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h
@@ -0,0 +1,97 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_GZIPDECOMPRESSORINPUTSTREAM_H_INCLUDED
+#define JUCE_GZIPDECOMPRESSORINPUTSTREAM_H_INCLUDED
+
+
+//==============================================================================
+/**
+ This stream will decompress a source-stream using zlib.
+
+ Tip: if you're reading lots of small items from one of these streams, you
+ can increase the performance enormously by passing it through a
+ BufferedInputStream, so that it has to read larger blocks less often.
+
+ @see GZIPCompressorOutputStream
+*/
+class JUCE_API GZIPDecompressorInputStream : public InputStream
+{
+public:
+ //==============================================================================
+ /** Creates a decompressor stream.
+
+ @param sourceStream the stream to read from
+ @param deleteSourceWhenDestroyed whether or not to delete the source stream
+ when this object is destroyed
+ @param noWrap this is used internally by the ZipFile class
+ and should be ignored by user applications
+ @param uncompressedStreamLength if the creator knows the length that the
+ uncompressed stream will be, then it can supply this
+ value, which will be returned by getTotalLength()
+ */
+ GZIPDecompressorInputStream (InputStream* sourceStream,
+ bool deleteSourceWhenDestroyed,
+ bool noWrap = false,
+ int64 uncompressedStreamLength = -1);
+
+ /** Creates a decompressor stream.
+
+ @param sourceStream the stream to read from - the source stream must not be
+ deleted until this object has been destroyed
+ */
+ GZIPDecompressorInputStream (InputStream& sourceStream);
+
+ /** Destructor. */
+ ~GZIPDecompressorInputStream();
+
+ //==============================================================================
+ int64 getPosition() override;
+ bool setPosition (int64 pos) override;
+ int64 getTotalLength() override;
+ bool isExhausted() override;
+ int read (void* destBuffer, int maxBytesToRead) override;
+
+private:
+ //==============================================================================
+ OptionalScopedPointer<InputStream> sourceStream;
+ const int64 uncompressedStreamLength;
+ const bool noWrap;
+ bool isEof;
+ int activeBufferSize;
+ int64 originalSourcePos, currentPos;
+ HeapBlock <uint8> buffer;
+
+ class GZIPDecompressHelper;
+ friend struct ContainerDeletePolicy<GZIPDecompressHelper>;
+ ScopedPointer<GZIPDecompressHelper> helper;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GZIPDecompressorInputStream)
+};
+
+#endif // JUCE_GZIPDECOMPRESSORINPUTSTREAM_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.cpp b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.cpp
new file mode 100644
index 0000000..a76d8b8
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.cpp
@@ -0,0 +1,608 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+class ZipFile::ZipEntryHolder
+{
+public:
+ ZipEntryHolder (const char* const buffer, const int fileNameLen)
+ {
+ entry.filename = String::fromUTF8 (buffer + 46, fileNameLen);
+
+ const int time = ByteOrder::littleEndianShort (buffer + 12);
+ const int date = ByteOrder::littleEndianShort (buffer + 14);
+ entry.fileTime = getFileTimeFromRawEncodings (time, date);
+
+ compressed = ByteOrder::littleEndianShort (buffer + 10) != 0;
+ compressedSize = (size_t) ByteOrder::littleEndianInt (buffer + 20);
+ entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24);
+
+ streamOffset = ByteOrder::littleEndianInt (buffer + 42);
+ }
+
+ struct FileNameComparator
+ {
+ static int compareElements (const ZipEntryHolder* first, const ZipEntryHolder* second)
+ {
+ return first->entry.filename.compare (second->entry.filename);
+ }
+ };
+
+ ZipEntry entry;
+ size_t streamOffset;
+ size_t compressedSize;
+ bool compressed;
+
+private:
+ static Time getFileTimeFromRawEncodings (int time, int date)
+ {
+ const int year = 1980 + (date >> 9);
+ const int month = ((date >> 5) & 15) - 1;
+ const int day = date & 31;
+ const int hours = time >> 11;
+ const int minutes = (time >> 5) & 63;
+ const int seconds = (time & 31) << 1;
+
+ return Time (year, month, day, hours, minutes, seconds);
+ }
+};
+
+//==============================================================================
+namespace
+{
+ int findEndOfZipEntryTable (InputStream& input, int& numEntries)
+ {
+ BufferedInputStream in (input, 8192);
+
+ in.setPosition (in.getTotalLength());
+ int64 pos = in.getPosition();
+ const int64 lowestPos = jmax ((int64) 0, pos - 1024);
+
+ char buffer [32] = { 0 };
+
+ while (pos > lowestPos)
+ {
+ in.setPosition (pos - 22);
+ pos = in.getPosition();
+ memcpy (buffer + 22, buffer, 4);
+
+ if (in.read (buffer, 22) != 22)
+ return 0;
+
+ for (int i = 0; i < 22; ++i)
+ {
+ if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50)
+ {
+ in.setPosition (pos + i);
+ in.read (buffer, 22);
+ numEntries = ByteOrder::littleEndianShort (buffer + 10);
+
+ return (int) ByteOrder::littleEndianInt (buffer + 16);
+ }
+ }
+ }
+
+ return 0;
+ }
+}
+
+//==============================================================================
+class ZipFile::ZipInputStream : public InputStream
+{
+public:
+ ZipInputStream (ZipFile& zf, ZipFile::ZipEntryHolder& zei)
+ : file (zf),
+ zipEntryHolder (zei),
+ pos (0),
+ headerSize (0),
+ inputStream (zf.inputStream)
+ {
+ if (zf.inputSource != nullptr)
+ {
+ inputStream = streamToDelete = file.inputSource->createInputStream();
+ }
+ else
+ {
+ #if JUCE_DEBUG
+ zf.streamCounter.numOpenStreams++;
+ #endif
+ }
+
+ char buffer [30];
+
+ if (inputStream != nullptr
+ && inputStream->setPosition ((int64) zei.streamOffset)
+ && inputStream->read (buffer, 30) == 30
+ && ByteOrder::littleEndianInt (buffer) == 0x04034b50)
+ {
+ headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26)
+ + ByteOrder::littleEndianShort (buffer + 28);
+ }
+ }
+
+ ~ZipInputStream()
+ {
+ #if JUCE_DEBUG
+ if (inputStream != nullptr && inputStream == file.inputStream)
+ file.streamCounter.numOpenStreams--;
+ #endif
+ }
+
+ int64 getTotalLength()
+ {
+ return (int64) zipEntryHolder.compressedSize;
+ }
+
+ int read (void* buffer, int howMany)
+ {
+ if (headerSize <= 0)
+ return 0;
+
+ howMany = (int) jmin ((int64) howMany, ((int64) zipEntryHolder.compressedSize) - pos);
+
+ if (inputStream == nullptr)
+ return 0;
+
+ int num;
+
+ if (inputStream == file.inputStream)
+ {
+ const ScopedLock sl (file.lock);
+ inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize);
+ num = inputStream->read (buffer, howMany);
+ }
+ else
+ {
+ inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize);
+ num = inputStream->read (buffer, howMany);
+ }
+
+ pos += num;
+ return num;
+ }
+
+ bool isExhausted()
+ {
+ return headerSize <= 0 || pos >= (int64) zipEntryHolder.compressedSize;
+ }
+
+ int64 getPosition()
+ {
+ return pos;
+ }
+
+ bool setPosition (int64 newPos)
+ {
+ pos = jlimit ((int64) 0, (int64) zipEntryHolder.compressedSize, newPos);
+ return true;
+ }
+
+private:
+ ZipFile& file;
+ ZipEntryHolder zipEntryHolder;
+ int64 pos;
+ int headerSize;
+ InputStream* inputStream;
+ ScopedPointer<InputStream> streamToDelete;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ZipInputStream)
+};
+
+
+//==============================================================================
+ZipFile::ZipFile (InputStream* const stream, const bool deleteStreamWhenDestroyed)
+ : inputStream (stream)
+{
+ if (deleteStreamWhenDestroyed)
+ streamToDelete = inputStream;
+
+ init();
+}
+
+ZipFile::ZipFile (InputStream& stream)
+ : inputStream (&stream)
+{
+ init();
+}
+
+ZipFile::ZipFile (const File& file)
+ : inputStream (nullptr),
+ inputSource (new FileInputSource (file))
+{
+ init();
+}
+
+ZipFile::ZipFile (InputSource* const source)
+ : inputStream (nullptr),
+ inputSource (source)
+{
+ init();
+}
+
+ZipFile::~ZipFile()
+{
+ entries.clear();
+}
+
+#if JUCE_DEBUG
+ZipFile::OpenStreamCounter::~OpenStreamCounter()
+{
+ /* If you hit this assertion, it means you've created a stream to read one of the items in the
+ zipfile, but you've forgotten to delete that stream object before deleting the file..
+ Streams can't be kept open after the file is deleted because they need to share the input
+ stream that is managed by the ZipFile object.
+ */
+ jassert (numOpenStreams == 0);
+}
+#endif
+
+//==============================================================================
+int ZipFile::getNumEntries() const noexcept
+{
+ return entries.size();
+}
+
+const ZipFile::ZipEntry* ZipFile::getEntry (const int index) const noexcept
+{
+ if (ZipEntryHolder* const zei = entries [index])
+ return &(zei->entry);
+
+ return nullptr;
+}
+
+int ZipFile::getIndexOfFileName (const String& fileName) const noexcept
+{
+ for (int i = 0; i < entries.size(); ++i)
+ if (entries.getUnchecked (i)->entry.filename == fileName)
+ return i;
+
+ return -1;
+}
+
+const ZipFile::ZipEntry* ZipFile::getEntry (const String& fileName) const noexcept
+{
+ return getEntry (getIndexOfFileName (fileName));
+}
+
+InputStream* ZipFile::createStreamForEntry (const int index)
+{
+ InputStream* stream = nullptr;
+
+ if (ZipEntryHolder* const zei = entries[index])
+ {
+ stream = new ZipInputStream (*this, *zei);
+
+ if (zei->compressed)
+ {
+ stream = new GZIPDecompressorInputStream (stream, true, true, (int64) zei->entry.uncompressedSize);
+
+ // (much faster to unzip in big blocks using a buffer..)
+ stream = new BufferedInputStream (stream, 32768, true);
+ }
+ }
+
+ return stream;
+}
+
+InputStream* ZipFile::createStreamForEntry (const ZipEntry& entry)
+{
+ for (int i = 0; i < entries.size(); ++i)
+ if (&entries.getUnchecked (i)->entry == &entry)
+ return createStreamForEntry (i);
+
+ return nullptr;
+}
+
+void ZipFile::sortEntriesByFilename()
+{
+ ZipEntryHolder::FileNameComparator sorter;
+ entries.sort (sorter);
+}
+
+//==============================================================================
+void ZipFile::init()
+{
+ ScopedPointer <InputStream> toDelete;
+ InputStream* in = inputStream;
+
+ if (inputSource != nullptr)
+ {
+ in = inputSource->createInputStream();
+ toDelete = in;
+ }
+
+ if (in != nullptr)
+ {
+ int numEntries = 0;
+ int pos = findEndOfZipEntryTable (*in, numEntries);
+
+ if (pos >= 0 && pos < in->getTotalLength())
+ {
+ const int size = (int) (in->getTotalLength() - pos);
+
+ in->setPosition (pos);
+ MemoryBlock headerData;
+
+ if (in->readIntoMemoryBlock (headerData, size) == (size_t) size)
+ {
+ pos = 0;
+
+ for (int i = 0; i < numEntries; ++i)
+ {
+ if (pos + 46 > size)
+ break;
+
+ const char* const buffer = static_cast <const char*> (headerData.getData()) + pos;
+
+ const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28);
+
+ if (pos + 46 + fileNameLen > size)
+ break;
+
+ entries.add (new ZipEntryHolder (buffer, fileNameLen));
+
+ pos += 46 + fileNameLen
+ + ByteOrder::littleEndianShort (buffer + 30)
+ + ByteOrder::littleEndianShort (buffer + 32);
+ }
+ }
+ }
+ }
+}
+
+Result ZipFile::uncompressTo (const File& targetDirectory,
+ const bool shouldOverwriteFiles)
+{
+ for (int i = 0; i < entries.size(); ++i)
+ {
+ Result result (uncompressEntry (i, targetDirectory, shouldOverwriteFiles));
+ if (result.failed())
+ return result;
+ }
+
+ return Result::ok();
+}
+
+Result ZipFile::uncompressEntry (const int index,
+ const File& targetDirectory,
+ bool shouldOverwriteFiles)
+{
+ const ZipEntryHolder* zei = entries.getUnchecked (index);
+
+ #if JUCE_WINDOWS
+ const String entryPath (zei->entry.filename);
+ #else
+ const String entryPath (zei->entry.filename.replaceCharacter ('\\', '/'));
+ #endif
+
+ const File targetFile (targetDirectory.getChildFile (entryPath));
+
+ if (entryPath.endsWithChar ('/') || entryPath.endsWithChar ('\\'))
+ return targetFile.createDirectory(); // (entry is a directory, not a file)
+
+ ScopedPointer<InputStream> in (createStreamForEntry (index));
+
+ if (in == nullptr)
+ return Result::fail ("Failed to open the zip file for reading");
+
+ if (targetFile.exists())
+ {
+ if (! shouldOverwriteFiles)
+ return Result::ok();
+
+ if (! targetFile.deleteFile())
+ return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName());
+ }
+
+ if (! targetFile.getParentDirectory().createDirectory())
+ return Result::fail ("Failed to create target folder: " + targetFile.getParentDirectory().getFullPathName());
+
+ {
+ FileOutputStream out (targetFile);
+
+ if (out.failedToOpen())
+ return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName());
+
+ out << *in;
+ }
+
+ targetFile.setCreationTime (zei->entry.fileTime);
+ targetFile.setLastModificationTime (zei->entry.fileTime);
+ targetFile.setLastAccessTime (zei->entry.fileTime);
+
+ return Result::ok();
+}
+
+
+//=============================================================================
+class ZipFile::Builder::Item
+{
+public:
+ Item (const File& f, InputStream* s, const int compression, const String& storedPath, Time time)
+ : file (f), stream (s), storedPathname (storedPath),
+ fileTime (time), compressionLevel (compression),
+ compressedSize (0), uncompressedSize (0), headerStart (0), checksum (0)
+ {
+ }
+
+ bool writeData (OutputStream& target, const int64 overallStartPosition)
+ {
+ MemoryOutputStream compressedData ((size_t) file.getSize());
+
+ if (compressionLevel > 0)
+ {
+ GZIPCompressorOutputStream compressor (&compressedData, compressionLevel, false,
+ GZIPCompressorOutputStream::windowBitsRaw);
+ if (! writeSource (compressor))
+ return false;
+ }
+ else
+ {
+ if (! writeSource (compressedData))
+ return false;
+ }
+
+ compressedSize = (int) compressedData.getDataSize();
+ headerStart = (int) (target.getPosition() - overallStartPosition);
+
+ target.writeInt (0x04034b50);
+ writeFlagsAndSizes (target);
+ target << storedPathname
+ << compressedData;
+
+ return true;
+ }
+
+ bool writeDirectoryEntry (OutputStream& target)
+ {
+ target.writeInt (0x02014b50);
+ target.writeShort (20); // version written
+ writeFlagsAndSizes (target);
+ target.writeShort (0); // comment length
+ target.writeShort (0); // start disk num
+ target.writeShort (0); // internal attributes
+ target.writeInt (0); // external attributes
+ target.writeInt (headerStart);
+ target << storedPathname;
+
+ return true;
+ }
+
+private:
+ const File file;
+ ScopedPointer<InputStream> stream;
+ String storedPathname;
+ Time fileTime;
+ int compressionLevel, compressedSize, uncompressedSize, headerStart;
+ unsigned long checksum;
+
+ static void writeTimeAndDate (OutputStream& target, Time t)
+ {
+ target.writeShort ((short) (t.getSeconds() + (t.getMinutes() << 5) + (t.getHours() << 11)));
+ target.writeShort ((short) (t.getDayOfMonth() + ((t.getMonth() + 1) << 5) + ((t.getYear() - 1980) << 9)));
+ }
+
+ bool writeSource (OutputStream& target)
+ {
+ if (stream == nullptr)
+ {
+ stream = file.createInputStream();
+
+ if (stream == nullptr)
+ return false;
+ }
+
+ checksum = 0;
+ uncompressedSize = 0;
+ const int bufferSize = 4096;
+ HeapBlock<unsigned char> buffer (bufferSize);
+
+ while (! stream->isExhausted())
+ {
+ const int bytesRead = stream->read (buffer, bufferSize);
+
+ if (bytesRead < 0)
+ return false;
+
+ checksum = zlibNamespace::crc32 (checksum, buffer, (unsigned int) bytesRead);
+ target.write (buffer, (size_t) bytesRead);
+ uncompressedSize += bytesRead;
+ }
+
+ stream = nullptr;
+ return true;
+ }
+
+ void writeFlagsAndSizes (OutputStream& target) const
+ {
+ target.writeShort (10); // version needed
+ target.writeShort ((short) (1 << 11)); // this flag indicates UTF-8 filename encoding
+ target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0);
+ writeTimeAndDate (target, fileTime);
+ target.writeInt ((int) checksum);
+ target.writeInt (compressedSize);
+ target.writeInt (uncompressedSize);
+ target.writeShort ((short) storedPathname.toUTF8().sizeInBytes() - 1);
+ target.writeShort (0); // extra field length
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Item)
+};
+
+//=============================================================================
+ZipFile::Builder::Builder() {}
+ZipFile::Builder::~Builder() {}
+
+void ZipFile::Builder::addFile (const File& file, const int compression, const String& path)
+{
+ items.add (new Item (file, nullptr, compression,
+ path.isEmpty() ? file.getFileName() : path,
+ file.getLastModificationTime()));
+}
+
+void ZipFile::Builder::addEntry (InputStream* stream, int compression, const String& path, Time time)
+{
+ jassert (stream != nullptr); // must not be null!
+ jassert (path.isNotEmpty());
+ items.add (new Item (File(), stream, compression, path, time));
+}
+
+bool ZipFile::Builder::writeToStream (OutputStream& target, double* const progress) const
+{
+ const int64 fileStart = target.getPosition();
+
+ for (int i = 0; i < items.size(); ++i)
+ {
+ if (progress != nullptr)
+ *progress = (i + 0.5) / items.size();
+
+ if (! items.getUnchecked (i)->writeData (target, fileStart))
+ return false;
+ }
+
+ const int64 directoryStart = target.getPosition();
+
+ for (int i = 0; i < items.size(); ++i)
+ if (! items.getUnchecked (i)->writeDirectoryEntry (target))
+ return false;
+
+ const int64 directoryEnd = target.getPosition();
+
+ target.writeInt (0x06054b50);
+ target.writeShort (0);
+ target.writeShort (0);
+ target.writeShort ((short) items.size());
+ target.writeShort ((short) items.size());
+ target.writeInt ((int) (directoryEnd - directoryStart));
+ target.writeInt ((int) (directoryStart - fileStart));
+ target.writeShort (0);
+
+ if (progress != nullptr)
+ *progress = 1.0;
+
+ return true;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.h
new file mode 100644
index 0000000..ccf9064
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/juce_ZipFile.h
@@ -0,0 +1,259 @@
+/*
+ ==============================================================================
+
+ This file is part of the juce_core module of the JUCE library.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+
+ Permission to use, copy, modify, and/or distribute this software for any purpose with
+ or without fee is hereby granted, provided that the above copyright notice and this
+ permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ------------------------------------------------------------------------------
+
+ NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
+ All other JUCE modules are covered by a dual GPL/commercial license, so if you are
+ using any other modules, be sure to check that you also comply with their license.
+
+ For more details, visit www.juce.com
+
+ ==============================================================================
+*/
+
+#ifndef JUCE_ZIPFILE_H_INCLUDED
+#define JUCE_ZIPFILE_H_INCLUDED
+
+
+//==============================================================================
+/**
+ Decodes a ZIP file from a stream.
+
+ This can enumerate the items in a ZIP file and can create suitable stream objects
+ to read each one.
+*/
+class JUCE_API ZipFile
+{
+public:
+ /** Creates a ZipFile based for a file. */
+ explicit ZipFile (const File& file);
+
+ //==============================================================================
+ /** Creates a ZipFile for a given stream.
+
+ @param inputStream the stream to read from
+ @param deleteStreamWhenDestroyed if set to true, the object passed-in
+ will be deleted when this ZipFile object is deleted
+ */
+ ZipFile (InputStream* inputStream, bool deleteStreamWhenDestroyed);
+
+ /** Creates a ZipFile for a given stream.
+ The stream will not be owned or deleted by this class - if you want the ZipFile to
+ manage the stream's lifetime, use the other constructor.
+ */
+ explicit ZipFile (InputStream& inputStream);
+
+ /** Creates a ZipFile for an input source.
+
+ The inputSource object will be owned by the zip file, which will delete
+ it later when not needed.
+ */
+ explicit ZipFile (InputSource* inputSource);
+
+ /** Destructor. */
+ ~ZipFile();
+
+ //==============================================================================
+ /**
+ Contains information about one of the entries in a ZipFile.
+
+ @see ZipFile::getEntry
+ */
+ struct ZipEntry
+ {
+ /** The name of the file, which may also include a partial pathname. */
+ String filename;
+
+ /** The file's original size. */
+ unsigned int uncompressedSize;
+
+ /** The last time the file was modified. */
+ Time fileTime;
+ };
+
+ //==============================================================================
+ /** Returns the number of items in the zip file. */
+ int getNumEntries() const noexcept;
+
+ /** Returns a structure that describes one of the entries in the zip file.
+
+ This may return zero if the index is out of range.
+
+ @see ZipFile::ZipEntry
+ */
+ const ZipEntry* getEntry (int index) const noexcept;
+
+ /** Returns the index of the first entry with a given filename.
+
+ This uses a case-sensitive comparison to look for a filename in the
+ list of entries. It might return -1 if no match is found.
+
+ @see ZipFile::ZipEntry
+ */
+ int getIndexOfFileName (const String& fileName) const noexcept;
+
+ /** Returns a structure that describes one of the entries in the zip file.
+
+ This uses a case-sensitive comparison to look for a filename in the
+ list of entries. It might return 0 if no match is found.
+
+ @see ZipFile::ZipEntry
+ */
+ const ZipEntry* getEntry (const String& fileName) const noexcept;
+
+ /** Sorts the list of entries, based on the filename.
+ */
+ void sortEntriesByFilename();
+
+ //==============================================================================
+ /** Creates a stream that can read from one of the zip file's entries.
+
+ The stream that is returned must be deleted by the caller (and
+ zero might be returned if a stream can't be opened for some reason).
+
+ The stream must not be used after the ZipFile object that created
+ has been deleted.
+ */
+ InputStream* createStreamForEntry (int index);
+
+ /** Creates a stream that can read from one of the zip file's entries.
+
+ The stream that is returned must be deleted by the caller (and
+ zero might be returned if a stream can't be opened for some reason).
+
+ The stream must not be used after the ZipFile object that created
+ has been deleted.
+ */
+ InputStream* createStreamForEntry (const ZipEntry& entry);
+
+ //==============================================================================
+ /** Uncompresses all of the files in the zip file.
+
+ This will expand all the entries into a target directory. The relative
+ paths of the entries are used.
+
+ @param targetDirectory the root folder to uncompress to
+ @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones
+ @returns success if the file is successfully unzipped
+ */
+ Result uncompressTo (const File& targetDirectory,
+ bool shouldOverwriteFiles = true);
+
+ /** Uncompresses one of the entries from the zip file.
+
+ This will expand the entry and write it in a target directory. The entry's path is used to
+ determine which subfolder of the target should contain the new file.
+
+ @param index the index of the entry to uncompress - this must be a valid index
+ between 0 and (getNumEntries() - 1).
+ @param targetDirectory the root folder to uncompress into
+ @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones
+ @returns success if all the files are successfully unzipped
+ */
+ Result uncompressEntry (int index,
+ const File& targetDirectory,
+ bool shouldOverwriteFiles = true);
+
+
+ //==============================================================================
+ /** Used to create a new zip file.
+
+ Create a ZipFile::Builder object, and call its addFile() method to add some files,
+ then you can write it to a stream with write().
+
+ Currently this just stores the files with no compression.. That will be added
+ soon!
+ */
+ class Builder
+ {
+ public:
+ Builder();
+ ~Builder();
+
+ /** Adds a file while should be added to the archive.
+ The file isn't read immediately, all the files will be read later when the writeToStream()
+ method is called.
+
+ The compressionLevel can be between 0 (no compression), and 9 (maximum compression).
+ If the storedPathName parameter is specified, you can customise the partial pathname that
+ will be stored for this file.
+ */
+ void addFile (const File& fileToAdd, int compressionLevel,
+ const String& storedPathName = String::empty);
+
+ /** Adds a file while should be added to the archive.
+
+ @param streamToRead this stream isn't read immediately - a pointer to the stream is
+ stored, then used later when the writeToStream() method is called, and
+ deleted by the Builder object when no longer needed, so be very careful
+ about its lifetime and the lifetime of any objects on which it depends!
+ This must not be null.
+ @param compressionLevel this can be between 0 (no compression), and 9 (maximum compression).
+ @param storedPathName the partial pathname that will be stored for this file
+ @param fileModificationTime the timestamp that will be stored as the last modification time
+ of this entry
+ */
+ void addEntry (InputStream* streamToRead, int compressionLevel,
+ const String& storedPathName, Time fileModificationTime);
+
+ /** Generates the zip file, writing it to the specified stream.
+ If the progress parameter is non-null, it will be updated with an approximate
+ progress status between 0 and 1.0
+ */
+ bool writeToStream (OutputStream& target, double* progress) const;
+
+ //==============================================================================
+ private:
+ class Item;
+ friend struct ContainerDeletePolicy<Item>;
+ OwnedArray<Item> items;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Builder)
+ };
+
+private:
+ //==============================================================================
+ class ZipInputStream;
+ class ZipEntryHolder;
+ friend class ZipInputStream;
+ friend class ZipEntryHolder;
+
+ OwnedArray <ZipEntryHolder> entries;
+ CriticalSection lock;
+ InputStream* inputStream;
+ ScopedPointer <InputStream> streamToDelete;
+ ScopedPointer <InputSource> inputSource;
+
+ #if JUCE_DEBUG
+ struct OpenStreamCounter
+ {
+ OpenStreamCounter() : numOpenStreams (0) {}
+ ~OpenStreamCounter();
+
+ int numOpenStreams;
+ };
+
+ OpenStreamCounter streamCounter;
+ #endif
+
+ void init();
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ZipFile)
+};
+
+#endif // JUCE_ZIPFILE_H_INCLUDED
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/README b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/README
new file mode 100644
index 0000000..758cc50
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/README
@@ -0,0 +1,125 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.3 is a general purpose data compression library. All the code is
+thread safe. The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format). These documents are also available in other
+formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib at gzip.org). A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly. Another example is given in the file minigzip.c. The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile. In short "make test; make install" should work for most
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
+
+Questions about zlib should be sent to <zlib at gzip.org>, or to Gilles Vollant
+<info at winimage.com> for the Windows DLL version. The zlib home page is
+http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
+please check this site to verify that you have the latest version of zlib;
+otherwise get the latest version and check whether the problem still exists or
+not.
+
+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
+for help.
+
+Mark Nelson <markn at ieee.org> wrote an article about zlib for the Jan. 1997
+issue of Dr. Dobb's Journal; a copy of the article is available in
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+
+The changes made in version 1.2.3 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory "contrib".
+
+A Java implementation of zlib is available in the Java Development Kit
+http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
+See the zlib home page http://www.zlib.org for details.
+
+A Perl interface to zlib written by Paul Marquess <pmqs at cpan.org> is in the
+CPAN (Comprehensive Perl Archive Network) sites
+http://www.cpan.org/modules/by-module/Compress/
+
+A Python interface to zlib written by A.M. Kuchling <amk at amk.ca> is
+available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html
+
+A zlib binding for TCL written by Andreas Kupries <a.kupries at westend.com> is
+availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info at winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+ -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+ compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+ when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+ necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+ other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+- When building a shared, i.e. dynamic library on Mac OS X, the library must be
+ installed before testing (do "make install" before "make test"), since the
+ library location is specified in the library.
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate
+ and zlib specifications were written by L. Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib;
+ they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup at gzip.org madler at alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/adler32.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/adler32.c
new file mode 100644
index 0000000..bf5cbd2
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/adler32.c
@@ -0,0 +1,143 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ rem = (unsigned)(len2 % BASE);
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 > BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/compress.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/compress.c
new file mode 100644
index 0000000..05c49c5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/compress.c
@@ -0,0 +1,70 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: compress.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen, int level)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (uLong sourceLen)
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.c
new file mode 100644
index 0000000..500d536
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.c
@@ -0,0 +1,407 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64 at csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id: crc32.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+# ifdef STDC /* need ANSI C limits.h to determine sizes */
+# include <limits.h>
+# define BYFOUR
+# if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int u4;
+# else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short u4;
+# else
+# undef BYFOUR /* can't find a four-byte integer type! */
+# endif
+# endif
+# endif
+# endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+ (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+ local unsigned long crc32_little OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+ local unsigned long crc32_big OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+# define TBLS 8
+#else
+# define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The first table is simply the CRC of all possible eight bit values. This is
+ all the information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes. The remaining tables
+ allow for word-at-a-time CRC calculation for both big-endian and little-
+ endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+ unsigned long c;
+ int n, k;
+ unsigned long poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static volatile int first = 1; /* flag to limit concurrent making */
+ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* See if another task is already doing this (not thread-safe, but better
+ than nothing -- significantly reduces duration of vulnerability in
+ case the advice about DYNAMIC_CRC_TABLE is ignored) */
+ if (first) {
+ first = 0;
+
+ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+ poly = 0UL;
+ for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+ poly |= 1UL << (31 - p[n]);
+
+ /* generate a crc for every 8-bit value */
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[0][n] = c;
+ }
+
+#ifdef BYFOUR
+ /* generate crc for each value followed by one, two, and three zeros,
+ and then the byte reversal of those as well as the first table */
+ for (n = 0; n < 256; n++) {
+ c = crc_table[0][n];
+ crc_table[4][n] = REV(c);
+ for (k = 1; k < 4; k++) {
+ c = crc_table[0][c & 0xff] ^ (c >> 8);
+ crc_table[k][n] = c;
+ crc_table[k + 4][n] = REV(c);
+ }
+ }
+#endif /* BYFOUR */
+
+ crc_table_empty = 0;
+ }
+ else { /* not first */
+ /* wait for the other guy to finish (not efficient, but rare) */
+ while (crc_table_empty)
+ ;
+ }
+
+#ifdef MAKECRCH
+ /* write out CRC tables to crc32.h */
+ {
+ FILE *out;
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+ fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+ fprintf(out, "local const unsigned long FAR ");
+ fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
+ write_table(out, crc_table[0]);
+# ifdef BYFOUR
+ fprintf(out, "#ifdef BYFOUR\n");
+ for (k = 1; k < 8; k++) {
+ fprintf(out, " },\n {\n");
+ write_table(out, crc_table[k]);
+ }
+ fprintf(out, "#endif\n");
+# endif /* BYFOUR */
+ fprintf(out, " }\n};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+ FILE *out;
+ const unsigned long FAR *table;
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
+ n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32 (unsigned long crc, const unsigned char FAR *buf, unsigned len)
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = (u4) (crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24])
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len)
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = (u4)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = (u4) (crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8));
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = (u4) (crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8));
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = (u4) (crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24])
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big (unsigned long crc, const unsigned char FAR *buf, unsigned len)
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = REV((u4)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = (u4) (crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8));
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = (u4) (crc_table[4][(c >> 24) ^ (u4) *buf++] ^ (c << 8));
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times (unsigned long *mat, unsigned long vec)
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square (unsigned long *square, unsigned long *mat)
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine (uLong crc1, uLong crc2, z_off_t len2)
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case */
+ if (len2 == 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320L; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.h
new file mode 100644
index 0000000..5de49bc
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+#ifdef BYFOUR
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+#endif
+ }
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.c
new file mode 100644
index 0000000..4b8bda5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.c
@@ -0,0 +1,1679 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: deflate.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size)
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_ (z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength)
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->wrap == 2 ||
+ (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+ return Z_STREAM_ERROR;
+
+ s = strm->state;
+ if (s->wrap)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+
+ (void) hash_head; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (z_streamp strm)
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (z_streamp strm, int bits, int value)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ strm->state->bi_valid = bits;
+ strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams (z_streamp strm, int level, int strategy)
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune (z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound (z_streamp strm, uLong sourceLen)
+{
+ deflate_state *s;
+ uLong destLen;
+
+ /* conservative upper bound */
+ destLen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+ /* if can't get parameters, return conservative bound */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return destLen;
+
+ /* if not default parameters, return conservative bound */
+ s = strm->state;
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return destLen;
+
+ /* default settings: return tight bound for that case */
+ return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (deflate_state *s, uInt b)
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending (z_streamp strm)
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (z_streamp strm, int flush)
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (z_streamp strm)
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (z_streamp dest, z_streamp source)
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy(dest, source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf (z_streamp strm, Bytef *buf, unsigned size)
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, strm->next_in, len);
+ }
+#endif
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (deflate_state *s)
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match)
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast (deflate_state *s, IPos cur_match)
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(deflate_state *s, IPos start, IPos match, int length)
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window (deflate_state *s)
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ /* %%% avoid this when Z_RLE */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(deflate_state *s, int flush)
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(deflate_state *s, int flush)
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+#ifdef FASTEST
+ if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+ (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#else
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#endif
+ /* longest_match() or longest_match_fast() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(deflate_state *s, int flush)
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+ /* longest_match() or longest_match_fast() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt run; /* length of run */
+ uInt max; /* maximum length of run */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan; /* scan for end of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ run = 0;
+ if (s->strstart > 0) { /* if there is a previous byte, that is */
+ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ scan = s->window + s->strstart - 1;
+ prev = *scan++;
+ do {
+ if (*scan++ != prev)
+ break;
+ } while (++run < max);
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (run >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, run);
+ _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+ s->lookahead -= run;
+ s->strstart += run;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.h
new file mode 100644
index 0000000..a3bae5f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/deflate.h
@@ -0,0 +1,333 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: deflate.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+#define NO_DUMMY_DECL
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/infback.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/infback.c
new file mode 100644
index 0000000..c259d01
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/infback.c
@@ -0,0 +1,611 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables1 OF((struct inflate_state FAR *state));
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->write = 0;
+ state->whave = 0;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables1 (struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code thisx; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables1(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ thisx = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (thisx.val < 16) {
+ NEEDBITS(thisx.bits);
+ DROPBITS(thisx.bits);
+ state->lens[state->have++] = thisx.val;
+ }
+ else {
+ if (thisx.val == 16) {
+ NEEDBITS(thisx.bits + 2);
+ DROPBITS(thisx.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (thisx.val == 17) {
+ NEEDBITS(thisx.bits + 3);
+ DROPBITS(thisx.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(thisx.bits + 7);
+ DROPBITS(thisx.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ thisx = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (thisx.op && (thisx.op & 0xf0) == 0) {
+ last = thisx;
+ for (;;) {
+ thisx = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(thisx.bits);
+ state->length = (unsigned)thisx.val;
+
+ /* process literal */
+ if (thisx.op == 0) {
+ Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", thisx.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (thisx.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (thisx.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(thisx.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ thisx = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((thisx.op & 0xf0) == 0) {
+ last = thisx;
+ for (;;) {
+ thisx = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(thisx.bits);
+ if (thisx.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)thisx.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(thisx.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly -- write leftover output */
+ ret = Z_STREAM_END;
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left))
+ ret = Z_BUF_ERROR;
+ }
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default: /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Return unused input */
+ inf_leave:
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd (z_streamp strm)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.c
new file mode 100644
index 0000000..6ac383d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.c
@@ -0,0 +1,316 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast (z_streamp strm, unsigned start)
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code thisx; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ thisx = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(thisx.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(thisx.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", thisx.val));
+ PUP(out) = (unsigned char)(thisx.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(thisx.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ thisx = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(thisx.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(thisx.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(thisx.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ thisx = dcode[thisx.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ thisx = lcode[thisx.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.h
new file mode 100644
index 0000000..614fa78
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffixed.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffixed.h
new file mode 100644
index 0000000..423d5c5
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications. It
+ is part of the implementation of the compression library and
+ is subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.c
new file mode 100644
index 0000000..eef0d37
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.c
@@ -0,0 +1,1339 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset (z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime (z_streamp strm, int bits, int value)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1 << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size)
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_ (z_streamp strm, const char *version, int stream_size)
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables (struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+ state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow (z_streamp strm, unsigned out)
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate (z_streamp strm, int flush)
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code thisx; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ thisx = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (thisx.val < 16) {
+ NEEDBITS(thisx.bits);
+ DROPBITS(thisx.bits);
+ state->lens[state->have++] = thisx.val;
+ }
+ else {
+ if (thisx.val == 16) {
+ NEEDBITS(thisx.bits + 2);
+ DROPBITS(thisx.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (thisx.val == 17) {
+ NEEDBITS(thisx.bits + 3);
+ DROPBITS(thisx.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(thisx.bits + 7);
+ DROPBITS(thisx.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ thisx = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (thisx.op && (thisx.op & 0xf0) == 0) {
+ last = thisx;
+ for (;;) {
+ thisx = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(thisx.bits);
+ state->length = (unsigned)thisx.val;
+ if ((int)(thisx.op) == 0) {
+ Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", thisx.val));
+ state->mode = LIT;
+ break;
+ }
+ if (thisx.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (thisx.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(thisx.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ thisx = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((thisx.op & 0xf0) == 0) {
+ last = thisx;
+ for (;;) {
+ thisx = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + thisx.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(thisx.bits);
+ if (thisx.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)thisx.val;
+ state->extra = (unsigned)(thisx.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd (z_streamp strm)
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength)
+{
+ struct inflate_state FAR *state;
+ unsigned long id_;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id_ = adler32(0L, Z_NULL, 0);
+ id_ = adler32(id_, dictionary, dictLength);
+ if (id_ != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader (z_streamp strm, gz_headerp head)
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch (unsigned FAR *have, unsigned char FAR *buf, unsigned len)
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync (z_streamp strm)
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint (z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.h
new file mode 100644
index 0000000..31b1279
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inflate.h
@@ -0,0 +1,121 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFLATE_H_
+#define _INFLATE_H_
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
+
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.c
new file mode 100644
index 0000000..dfc0aa7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.c
@@ -0,0 +1,328 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table (codetype type,
+ unsigned short FAR *lens,
+ unsigned codes,
+ code FAR * FAR *table,
+ unsigned FAR *bits,
+ unsigned short FAR *work)
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code thisx; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ thisx.op = (unsigned char)64; /* invalid code marker */
+ thisx.bits = (unsigned char)1;
+ thisx.val = (unsigned short)0;
+ *(*table)++ = thisx; /* make a table to force an error */
+ *(*table)++ = thisx;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ thisx.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ thisx.op = (unsigned char)0;
+ thisx.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ thisx.op = (unsigned char)(extra[work[sym]]);
+ thisx.val = base[work[sym]];
+ }
+ else {
+ thisx.op = (unsigned char)(32 + 64); /* end of block */
+ thisx.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = thisx;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ thisx.op = (unsigned char)64; /* invalid code marker */
+ thisx.bits = (unsigned char)(len - drop);
+ thisx.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ thisx.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = thisx;
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.h
new file mode 100644
index 0000000..ea64af0
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/inftrees.h
@@ -0,0 +1,61 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFTREES_H_
+#define _INFTREES_H_
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
+
+
+#endif
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.c
new file mode 100644
index 0000000..36a124d
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.c
@@ -0,0 +1,1191 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id: trees.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits (deflate_state *s, int value, int length)
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += (int) (length - Buf_size);
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(deflate_state *s)
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block (deflate_state *s)
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap (deflate_state *s,
+ ct_data *tree, /* the tree to restore */
+ int k) /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen (deflate_state *s, tree_desc *desc)
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (ct_data *tree, /* the tree to decorate */
+ int max_code, /* largest code with non zero frequency */
+ ushf *bl_count) /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree (deflate_state *s,
+ tree_desc *desc) /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code) /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code) /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree (deflate_state *s)
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees (deflate_state *s,
+ int lcodes, int dcodes, int blcodes) /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block (deflate_state *s, charf *buf, ulg stored_len, int eof)
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align (deflate_state *s)
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block (deflate_state *s,
+ charf *buf, /* input block, or NULL if too old */
+ ulg stored_len, /* length of input block */
+ int eof) /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+ set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (deflate_state *s,
+ unsigned dist, /* distance of matched string */
+ unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block (deflate_state *s,
+ ct_data *ltree, /* literal tree */
+ ct_data *dtree) /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type (deflate_state *s)
+{
+ int n;
+
+ for (n = 0; n < 9; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ if (n == 9)
+ for (n = 14; n < 32; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse (unsigned code, int len)
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush (deflate_state *s)
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup (deflate_state *s)
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(deflate_state *s,
+ charf *buf, /* the input data */
+ unsigned len, /* its length */
+ int header) /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.h
new file mode 100644
index 0000000..5ac45a7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/trees.h
@@ -0,0 +1,127 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/uncompr.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/uncompr.c
new file mode 100644
index 0000000..839602f
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/uncompr.c
@@ -0,0 +1,60 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: uncompr.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (Bytef *dest,
+ uLongf *destLen,
+ const Bytef *source,
+ uLong sourceLen)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.h
new file mode 100644
index 0000000..f1e9e87
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.h
@@ -0,0 +1,345 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+// *** Just a few hacks here to make it compile nicely with Juce..
+#define Z_PREFIX 1
+#undef __MACTYPES__
+
+#ifdef _MSC_VER
+ #pragma warning (disable : 4131 4127 4244 4267)
+#endif
+
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define inflatePrime z_inflatePrime
+# define inflateGetHeader z_inflateGetHeader
+# define adler32_combine z_adler32_combine
+# define crc32_combine z_crc32_combine
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.in.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.in.h
new file mode 100644
index 0000000..018173a
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zconf.in.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.in.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zlib.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zlib.h
new file mode 100644
index 0000000..bdf8af7
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zlib.h
@@ -0,0 +1,1358 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup at gzip.org madler at alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+//ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+//ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+//}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.c b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.c
new file mode 100644
index 0000000..630305c
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.c
@@ -0,0 +1,311 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+/*const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch (sizeof(uInt)) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch (sizeof(uLong)) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch (sizeof(voidpf)) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch (sizeof(z_off_t)) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#ifdef STDC
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}*/
+
+#if 0
+
+# ifndef verbose
+# define verbose 0
+# endif
+int z_verbose = verbose;
+
+void z_error (const char *m)
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(int err)
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.h b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.h
new file mode 100644
index 0000000..3939858
--- /dev/null
+++ b/src/htio2/JUCE-3.0.8/modules/juce_core/zip/zlib/zutil.h
@@ -0,0 +1,271 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
+ extern int errno;
+#else
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || TARGET_OS_MAC
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#if 0
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((const char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+# define z_error(x)
+# define z_verbose 0
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/src/htio2/Kmer.cpp b/src/htio2/Kmer.cpp
new file mode 100644
index 0000000..70ace8b
--- /dev/null
+++ b/src/htio2/Kmer.cpp
@@ -0,0 +1,436 @@
+#include "htio2/Kmer.h"
+#include "htio2/Error.h"
+
+#include <cmath>
+
+#include <cstdio>
+#include <limits>
+
+using namespace std;
+
+namespace htio2
+{
+
+void encode_nt5(const std::string& seq, EncodedSeq& encoded_seq)
+{
+ const size_t len = seq.length();
+ encoded_seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ EncodedType curr = encode_nt5(seq[i]);
+ encoded_seq[i] = curr;
+ }
+}
+
+void encode_nt4(const string &seq, EncodedSeq &encoded_seq)
+{
+ const size_t len = seq.length();
+ encoded_seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ EncodedType curr = encode_nt4(seq[i]);
+ encoded_seq[i] = curr;
+ }
+}
+
+void encode_aa(const std::string& seq, EncodedSeq& encoded_seq)
+{
+ const size_t len = seq.length();
+ encoded_seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ EncodedType curr = encode_aa(seq[i]);
+ encoded_seq[i] = curr;
+ }
+}
+
+void decode_nt5(const EncodedSeq& encoded_seq, std::string& seq)
+{
+ const size_t len = encoded_seq.size();
+ seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ char curr = decode_nt5(encoded_seq[i]);
+ seq[i] = curr;
+ }
+}
+
+void decode_nt4(const EncodedSeq &encoded_seq, string &seq)
+{
+ const size_t len = encoded_seq.size();
+ seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ char curr = decode_nt4(encoded_seq[i]);
+ seq[i] = curr;
+ }
+}
+
+void decode_aa(const EncodedSeq& encoded_seq, std::string& seq)
+{
+ const size_t len = encoded_seq.size();
+ seq.resize(len);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ char curr = decode_aa(encoded_seq[i]);
+ seq[i] = curr;
+ }
+}
+
+template <EncodedType nary>
+inline void _revcom_(const EncodedSeq& in, EncodedSeq& out)
+{
+ const size_t len = in.size();
+ out.resize(len);
+ for (size_t i = 0; i < len; i++)
+ {
+ const EncodedType curr = in[i];
+ size_t i_out = len - i - 1;
+ if (curr == ENCODED_ERROR)
+ out[i_out] = ENCODED_ERROR;
+ else
+ out[i_out] = nary - curr;
+ }
+}
+
+void revcom_nt5(const EncodedSeq& in, EncodedSeq& out)
+{
+ _revcom_<5>(in, out);
+}
+
+void revcom_nt4(const EncodedSeq& in, EncodedSeq& out)
+{
+ _revcom_<4>(in, out);
+}
+
+bool operator==(const EncodedSeq& a, const EncodedSeq& b)
+{
+ const size_t len = a.size();
+ if (len == b.size())
+ return false;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ if (a[i] != b[i]) return false;
+ }
+
+ return true;
+}
+
+template <typename kmer_type, int nary>
+inline bool gen_kmer_impl(const EncodedSeq& encoded_seq, vector<kmer_type>& result, size_t kmer_size)
+{
+ if (kmer_size > KmerTrait<nary, kmer_type>::max_size())
+ return false;
+
+ size_t len = encoded_seq.size();
+ if (len < kmer_size)
+ return false;
+
+ const size_t num_kmer = len - kmer_size + 1;
+ result.resize(num_kmer);
+
+ const size_t digit_base = std::pow(nary, kmer_size-1);
+ size_t i_begin = 0;
+ const size_t i_end = num_kmer;
+
+ for (;;)
+ {
+ if (i_begin >= i_end) break;
+
+ // build the first kmer
+ bool init_got_unusable = false;
+ size_t kmer = 0;
+
+ for (size_t k = 0; k < kmer_size; ++k)
+ {
+ size_t i = i_begin + k;
+ EncodedType curr = encoded_seq[i];
+
+ if (curr != ENCODED_ERROR)
+ kmer += curr * std::pow(nary, k);
+ else
+ {
+ // mark affected position as error
+ for (size_t i_error = i_begin;
+ i_error <= i && i_error < i_end;
+ ++i_error)
+ {
+ result[i_error] = numeric_limits<kmer_type>::max();
+ }
+
+ // skip to the base next to unusable
+ i_begin += k + 1;
+ init_got_unusable = true;
+ break;
+ }
+ }
+
+ // if got unusable, build first kmer again again
+ if (init_got_unusable)
+ continue;
+
+ result[i_begin] = kmer;
+
+ // elongate kmer
+ // each time, read one base, and remove previoius base
+ bool elong_got_error = false;
+ for (size_t i = i_begin + 1; i < i_end; ++i)
+ {
+ size_t i_kmer_tail = i + kmer_size - 1;
+ EncodedType prev_enc = encoded_seq[i - 1];
+ EncodedType tail_enc = encoded_seq[i_kmer_tail];
+
+ if (tail_enc != ENCODED_ERROR)
+ {
+ kmer -= prev_enc;
+ kmer /= nary;
+ kmer += tail_enc * digit_base;
+ result[i] = kmer;
+ }
+ else
+ {
+ // mark affected position as error
+ for (size_t i_error = i;
+ i_error <= i_kmer_tail && i_error < i_end;
+ ++i_error)
+ {
+ result[i_error] = numeric_limits<kmer_type>::max();
+ }
+
+ // skip to the base next to unusable
+ i_begin = i_kmer_tail + 1;
+ elong_got_error = true;
+ break;
+ }
+ }
+
+ // if we don't get any unusable base, we've finished everything
+ if (elong_got_error)
+ continue;
+ else
+ break;
+ }
+
+ return true;
+}
+
+typedef void (*encode_func) (const std::string& seq, EncodedSeq& encoded_seq);
+
+template<typename kmer_type, int nary>
+inline kmer_type gen_kmer_simple_impl(encode_func func, const std::string& seq)
+{
+ if (seq.length() > KmerTrait<nary, kmer_type>::max_size())
+ return numeric_limits<kmer_type>::max();
+
+ EncodedSeq enc;
+ func(seq, enc);
+
+ const size_t size = seq.length();
+ kmer_type kmer = 0;
+ kmer_type digit_base = 1;
+ for (size_t i = 0; i < size; i++)
+ {
+ if (enc[i] == ENCODED_ERROR)
+ {
+ kmer = numeric_limits<kmer_type>::max();
+ break;
+ }
+ kmer += enc[i] * digit_base;
+ digit_base *= nary;
+ }
+ return kmer;
+}
+
+template<>
+bool gen_kmer_nt5<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint64_t, 5>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_nt5<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint32_t, 5>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_nt5<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint16_t, 5>(encoded_seq, result, kmer_size);
+}
+
+template<>
+uint64_t gen_kmer_nt5<uint64_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint64_t, 5>(encode_nt5, seq);
+}
+
+template<>
+uint32_t gen_kmer_nt5<uint32_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint32_t, 5>(encode_nt5, seq);
+}
+
+template<>
+uint16_t gen_kmer_nt5<uint16_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint16_t, 5>(encode_nt5, seq);
+}
+
+template<>
+bool gen_kmer_nt4<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint64_t, 4>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_nt4<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint32_t, 4>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_nt4<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint16_t, 4>(encoded_seq, result, kmer_size);
+}
+
+template<>
+uint64_t gen_kmer_nt4<uint64_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint64_t, 4>(encode_nt4, seq);
+}
+
+template<>
+uint32_t gen_kmer_nt4<uint32_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint32_t, 4>(encode_nt4, seq);
+}
+
+template<>
+uint16_t gen_kmer_nt4<uint16_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint16_t, 4>(encode_nt4, seq);
+}
+
+template<>
+bool gen_kmer_aa<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint64_t, 26>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_aa<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint32_t, 26>(encoded_seq, result, kmer_size);
+}
+
+template<>
+bool gen_kmer_aa<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size)
+{
+ return gen_kmer_impl<uint16_t, 26>(encoded_seq, result, kmer_size);
+}
+
+template<>
+uint64_t gen_kmer_aa<uint64_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint64_t, 26>(encode_aa, seq);
+}
+
+template<>
+uint32_t gen_kmer_aa<uint32_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint32_t, 26>(encode_aa, seq);
+}
+
+template<>
+uint16_t gen_kmer_aa<uint16_t>(const std::string& seq)
+{
+ return gen_kmer_simple_impl<uint16_t, 26>(encode_aa, seq);
+}
+
+typedef char (*decode_func_type)(EncodedType input);
+
+template<typename kmer_type, int nary>
+inline string decode_kmer_impl(decode_func_type decode_func, kmer_type kmer, size_t kmer_size)
+{
+ string result;
+ if (kmer == numeric_limits<kmer_type>::max())
+ return result;
+// printf("decode %d-ary %lu-mer %lu\n", nary, kmer_size, uint64_t(kmer));
+
+ for (size_t i=0; i<kmer_size; i++)
+ {
+ EncodedType enc = kmer % nary;
+ char dec = decode_func(enc);
+// printf(" %lu: residue %c (%d) from %lu\n", i, dec, int(enc), uint64_t(kmer));
+ result.push_back(dec);
+ kmer -= enc;
+ kmer /= nary;
+ }
+
+ return result;
+}
+
+template<>
+std::string decode_kmer_nt5<uint64_t>(uint64_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint64_t, 5>(decode_nt5, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_nt5<uint32_t>(uint32_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint32_t, 5>(decode_nt5, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_nt5<uint16_t>(uint16_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint16_t, 5>(decode_nt5, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_nt4<uint64_t>(uint64_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint64_t, 4>(decode_nt4, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_nt4<uint32_t>(uint32_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint32_t, 4>(decode_nt4, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_nt4<uint16_t>(uint16_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint16_t, 4>(decode_nt4, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_aa<uint64_t>(uint64_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint64_t, 26>(decode_aa, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_aa<uint32_t>(uint32_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint32_t, 26>(decode_aa, kmer, kmer_size);
+}
+
+template<>
+std::string decode_kmer_aa<uint16_t>(uint16_t kmer, size_t kmer_size)
+{
+ return decode_kmer_impl<uint16_t, 26>(decode_aa, kmer, kmer_size);
+}
+
+} // namespace htio2
diff --git a/src/htio2/Kmer.h b/src/htio2/Kmer.h
new file mode 100644
index 0000000..277de23
--- /dev/null
+++ b/src/htio2/Kmer.h
@@ -0,0 +1,553 @@
+#ifndef HTIO2_KMER_H
+#define HTIO2_KMER_H
+
+#include <vector>
+#include <map>
+
+#include <stdint.h>
+
+#include "htio2/Enum.h"
+
+namespace htio2
+{
+
+typedef enum
+{
+ SEQ_TYPE_NT4 = 0,
+ SEQ_TYPE_NT5 = 1,
+ SEQ_TYPE_AA = 2,
+} SeqType;
+
+typedef uint8_t EncodedType;
+#define ENCODED_ERROR 255
+//#define RESIDUE_ERROR -1
+typedef std::vector<EncodedType> EncodedSeq;
+
+#define KMER_NT4_LIMIT_64 31
+#define KMER_NT4_LIMIT_32 15
+#define KMER_NT4_LIMIT_16 7
+#define KMER_NT5_LIMIT_64 27
+#define KMER_NT5_LIMIT_32 13
+#define KMER_NT5_LIMIT_16 6
+#define KMER_AA_LIMIT_64 13
+#define KMER_AA_LIMIT_32 6
+#define KMER_AA_LIMIT_16 3
+
+/**
+ * Properties for a N-ary kmer stored in a primitive data type of specific size.
+ */
+template<int nary, typename KmerType>
+struct KmerTrait;
+
+template<>
+struct KmerTrait<4, uint64_t>
+{
+ static size_t max_size() { return KMER_NT4_LIMIT_64; }
+};
+
+template<>
+struct KmerTrait<4, uint32_t>
+{
+ static size_t max_size() { return KMER_NT4_LIMIT_32; }
+};
+
+template<>
+struct KmerTrait<4, uint16_t>
+{
+ static size_t max_size() { return KMER_NT4_LIMIT_16; }
+};
+
+template<>
+struct KmerTrait<5, uint64_t>
+{
+ static size_t max_size() { return KMER_NT5_LIMIT_64; }
+};
+
+template<>
+struct KmerTrait<5, uint32_t>
+{
+ static size_t max_size() { return KMER_NT5_LIMIT_32; }
+};
+
+template<>
+struct KmerTrait<5, uint16_t>
+{
+ static size_t max_size() { return KMER_NT5_LIMIT_16; }
+};
+
+template<>
+struct KmerTrait<26, uint64_t>
+{
+ static size_t max_size() { return KMER_AA_LIMIT_64; }
+};
+
+template<>
+struct KmerTrait<26, uint32_t>
+{
+ static size_t max_size() { return KMER_AA_LIMIT_32; }
+};
+
+template<>
+struct KmerTrait<26, uint16_t>
+{
+ static size_t max_size() { return KMER_AA_LIMIT_16; }
+};
+
+
+#define ENCODED_NT5_A 0
+#define ENCODED_NT5_T 4
+#define ENCODED_NT5_G 1
+#define ENCODED_NT5_C 3
+#define ENCODED_NT5_N 2
+
+/**
+ * map ATGCN to numbers 0-4, and map all other characters to 255
+ * @param input a nucleotide in ATGCN
+ * @return a number from 0 to 4
+ */
+inline EncodedType encode_nt5(char input)
+{
+ switch (input)
+ {
+ case 'A':
+ case 'a':
+ return ENCODED_NT5_A;
+ case 'T':
+ case 't':
+ return ENCODED_NT5_T;
+ case 'G':
+ case 'g':
+ return ENCODED_NT5_G;
+ case 'C':
+ case 'c':
+ return ENCODED_NT5_C;
+ case 'N':
+ case 'n':
+ return ENCODED_NT5_N;
+ default:
+ return ENCODED_ERROR;
+ }
+}
+
+
+#define ENCODED_NT4_A 0
+#define ENCODED_NT4_T 3
+#define ENCODED_NT4_G 1
+#define ENCODED_NT4_C 2
+
+/**
+ * map ATGC to numbers 0-3, and map all other characters to 255
+ * @param input a nucleotide in ATGC
+ * @return a number from 0 to 3
+ */
+inline EncodedType encode_nt4(char input)
+{
+ switch (input)
+ {
+ case 'A':
+ case 'a':
+ return ENCODED_NT4_A;
+ case 'T':
+ case 't':
+ return ENCODED_NT4_T;
+ case 'G':
+ case 'g':
+ return ENCODED_NT4_G;
+ case 'C':
+ case 'c':
+ return ENCODED_NT4_C;
+ default:
+ return ENCODED_ERROR;
+ }
+}
+
+/**
+ * map amino acids residues to 0-25, "*" to 'O' minus 'A', and all other characters to 255
+ * @param input a amino acids residue
+ * @return numbers from 0 to 25.
+ */
+inline EncodedType encode_aa(char input)
+{
+ if (input == '*') input = 'O';
+
+ if ('a' <= input && input <= 'z') return input - 'a';
+ else if ('A' <= input && input <= 'Z') return input - 'A';
+ else return ENCODED_ERROR;
+}
+
+/**
+ * Map encoded nucleotides back to characters: 0-4 will be mapped to ATGCN;
+ * character '-' and '.' will be specially treated, which will be returned
+ * as-is; and all other characters will be mapped to 'N'.
+ *
+ * @param input encoded bases in 0-4
+ * @return bases in ATGCN.
+ *
+ * @see encode_nt5(char);
+ */
+inline char decode_nt5(EncodedType input)
+{
+ switch (input)
+ {
+ case ENCODED_NT5_A:
+ return 'A';
+ case ENCODED_NT5_T:
+ return 'T';
+ case ENCODED_NT5_G:
+ return 'G';
+ case 3:
+ return 'C';
+ case '-':
+ case '.':
+ return input;
+ case 2:
+ default:
+ return 'N';
+ }
+}
+
+/**
+ * Map encoded nucleotides back to characters: 0-3 will be mapped to ATGC;
+ * character '-' and '.' will be specially treated, which will be returned
+ * as-is; and all other characters will be mapped to 'N'.
+ *
+ * @param input encoded bases in 0-4
+ * @return bases in ATGCN.
+ *
+ * @see encode_nt4(char)
+ */
+inline char decode_nt4(EncodedType input)
+{
+ switch (input)
+ {
+ case 0:
+ return 'A';
+ case 3:
+ return 'T';
+ case 1:
+ return 'G';
+ case 2:
+ return 'C';
+ case '-':
+ case '.':
+ return input;
+ default:
+ return 'N';
+ }
+}
+
+/**
+ * Map encoded amino acids residues back to characters: nomal residues will
+ * be mapped back to characters; 'O' minus 'A' will be mapped to '*'; other
+ * things will be mapped to 'X'.
+ *
+ * @param input residues in 0-25
+ * @return residues in characters.
+ *
+ * @see encode_aa(char);
+ */
+inline char decode_aa(EncodedType input)
+{
+ char result;
+ if (0 <= input && input <= 25)
+ result = input + 'A';
+ else if (input == '-' || input == '.')
+ result = input;
+ else
+ result = 'X';
+
+ if (result == 'O') result = '*';
+
+ return result;
+}
+
+/**
+ * Encode a string of nucleotides, ATGCN are allowed.
+ * @param seq input sequence
+ * @param encoded_seq object to store encoded result
+ *
+ * @see encode_nt5(char)
+ */
+void encode_nt5(const std::string& seq, EncodedSeq& encoded_seq);
+
+/**
+ * Encode a string of nucleotides, ATGC are allowed.
+ * @param seq input sequence
+ * @param encoded_seq object to store encoded result
+ *
+ * @see encode_nt4(char)
+ */
+void encode_nt4(const std::string& seq, EncodedSeq& encoded_seq);
+
+/**
+ * Encode a string of amino acid residues.
+ * @param seq input sequence
+ * @param encoded_seq object to store encoded result
+ *
+ * @see encode_aa(char)
+ */
+void encode_aa(const std::string& seq, EncodedSeq& encoded_seq);
+
+/**
+ * Decode an array of encoded nucleotides.
+ *
+ * @param encoded_seq sequence to decode
+ * @param seq string object to store decoded result
+ *
+ * @see decode_nt5(EncodedType)
+ */
+void decode_nt5(const EncodedSeq& encoded_seq, std::string& seq);
+
+/**
+ * Decode an array of encoded nucleotides.
+ *
+ * @param encoded_seq sequence to decode
+ * @param seq string object to store decoded result
+ *
+ * @see decode_nt4(EncodedType)
+ */
+void decode_nt4(const EncodedSeq& encoded_seq, std::string& seq);
+
+/**
+ * Decode an array of encoded nucleotides.
+ *
+ * @param encoded_seq sequence to decode
+ * @param seq string object to store decoded result
+ *
+ * @see decode_aa(EncodedType)
+ */
+void decode_aa(const EncodedSeq& encoded_seq, std::string& seq);
+
+/**
+ * do reverse-complement for an encoded nucleotide sequence
+ * @param in input sequence containing encoded ATGCN
+ * @param out object to store result
+ */
+void revcom_nt5(const EncodedSeq& in, EncodedSeq& out);
+
+/**
+ * do reverse-complement for an encoded nucleotide sequence
+ * @param in input sequence containing encoded ATGC
+ * @param out object to store result
+ */
+void revcom_nt4(const EncodedSeq& in, EncodedSeq& out);
+
+/**
+ * test whether two encoded sequences are identical
+ * @param a
+ * @param b
+ * @return
+ */
+bool operator==(const EncodedSeq& a, const EncodedSeq& b);
+
+/**
+ * Generate a series of kmers along encoded nucleotide sequence. Each kmer is
+ * generated as a 5-ary number of K digits, and is stored in an unsigned
+ * integer of specified size. On positions where kmer has invalid base,
+ * TYPE_MAX will be set.
+ *
+ * @param encoded_seq encoded nucleotide sequence
+ * @param result series of generated kmers
+ * @param kmer_size
+ * @return false if kmer size is larger than input sequence, or kmer size is
+ * larger than allowed kmer size limit for specified data type.
+ */
+template<typename KmerType>
+bool gen_kmer_nt5(const EncodedSeq& encoded_seq, std::vector<KmerType>& result, size_t kmer_size);
+
+template<>
+bool gen_kmer_nt5<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_nt5<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_nt5<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size);
+
+/**
+ * Generate one kmer from nucleotide sequence in ATGCN. The kmer is generated
+ * as a 5-ary number of K digits, and is stored in an unsigned integer of
+ * specified size. The whole sequence is generated to one kmer, and sequence
+ * length is used as kmer size.
+ *
+ * @param seq input sequence
+ * @return generated kmer
+ */
+template<typename KmerType>
+KmerType gen_kmer_nt5(const std::string& seq);
+
+template<>
+uint64_t gen_kmer_nt5<uint64_t>(const std::string& seq);
+template<>
+uint32_t gen_kmer_nt5<uint32_t>(const std::string& seq);
+template<>
+uint16_t gen_kmer_nt5<uint16_t>(const std::string& seq);
+
+/**
+ * Generate a series of kmers along encoded nucleotide sequence. Each kmer is
+ * generated as a 4-ary number of K digits, and is stored in an unsigned
+ * integer of specified size. On positions where kmer has invalid base,
+ * TYPE_MAX will be set.
+ *
+ * @param encoded_seq encoded nucleotide sequence
+ * @param result series of generated kmers
+ * @param kmer_size
+ * @return false if kmer size is larger than input sequence, or kmer size is
+ * larger than allowed kmer size limit for specified data type.
+ */
+template<typename KmerType>
+bool gen_kmer_nt4(const EncodedSeq& encoded_seq, std::vector<KmerType>& result, size_t kmer_size);
+
+template<>
+bool gen_kmer_nt4<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_nt4<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_nt4<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size);
+
+
+/**
+ * Generate one kmer from nucleotide sequence in ATGC. The kmer is generated
+ * as a 4-ary number of K digits, and is stored in an unsigned integer of
+ * specified size. The whole sequence is generated to one kmer, and sequence
+ * length is used as kmer size.
+ *
+ * @param seq input sequence
+ * @return generated kmer
+ */
+template<typename KmerType>
+KmerType gen_kmer_nt4(const std::string& seq);
+
+template<>
+uint64_t gen_kmer_nt4<uint64_t>(const std::string& seq);
+template<>
+uint32_t gen_kmer_nt4<uint32_t>(const std::string& seq);
+template<>
+uint16_t gen_kmer_nt4<uint16_t>(const std::string& seq);
+
+/**
+ * Generate a series of kmers along encoded amino acids sequence. Each kmer is
+ * generated as a 26-ary number of K digits, and is stored in an unsigned
+ * integer of specified size. On positions where kmer has invalid base,
+ * TYPE_MAX will be set.
+ *
+ * @param encoded_seq encoded amino acids sequence
+ * @param result series of generated kmers
+ * @param kmer_size
+ * @return false if kmer size is larger than input sequence, or kmer size is
+ * larger than allowed kmer size limit for specified data type.
+ */
+template<typename KmerType>
+bool gen_kmer_aa(const EncodedSeq& encoded_seq, std::vector<KmerType>& result, size_t kmer_size);
+
+template<>
+bool gen_kmer_aa<uint64_t>(const EncodedSeq& encoded_seq, std::vector<uint64_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_aa<uint32_t>(const EncodedSeq& encoded_seq, std::vector<uint32_t>& result, size_t kmer_size);
+template<>
+bool gen_kmer_aa<uint16_t>(const EncodedSeq& encoded_seq, std::vector<uint16_t>& result, size_t kmer_size);
+
+/**
+ * Generate one kmer from amino acids sequence. The kmer is generated as a
+ * 26-ary number of K digits, and is stored in an unsigned integer of specified
+ * size. The whole sequence is generated to one kmer, and sequence length is
+ * used as kmer size.
+ *
+ * @param seq input sequence
+ * @return generated kmer
+ */
+template<typename KmerType>
+KmerType gen_kmer_aa(const std::string& seq);
+
+template<>
+uint64_t gen_kmer_aa<uint64_t>(const std::string& seq);
+template<>
+uint32_t gen_kmer_aa<uint32_t>(const std::string& seq);
+template<>
+uint16_t gen_kmer_aa<uint16_t>(const std::string& seq);
+
+/**
+ * test whether two series of kmers are identical
+ * @param a
+ * @param b
+ * @return
+ */
+template<typename KmerType>
+bool operator==(const std::vector<KmerType>& a, const std::vector<KmerType>& b)
+{
+ const size_t len = a.size();
+ if (len != b.size())
+ return false;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ if (a[i] != b[i])
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Generate mapping from kmer to position. Position is 0-based.
+ * @param kmer_list series of kmers
+ * @param kmer_pos a multimap with kmers as key.
+ */
+template<typename K, typename P>
+void summ_kmer_pos(const std::vector<K>& kmer_list, std::multimap<K, P>& result)
+{
+ for (P i = 0; i < kmer_list.size(); i++)
+ result.insert(std::make_pair(kmer_list[i], i));
+}
+
+/**
+ * decode nucleotide kmer to human-readable string
+ * @param kmer
+ * @param kmer_size
+ * @return
+ */
+template<typename KmerType>
+std::string decode_kmer_nt5(KmerType kmer, size_t kmer_size);
+
+template<>
+std::string decode_kmer_nt5<uint64_t>(uint64_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_nt5<uint32_t>(uint32_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_nt5<uint16_t>(uint16_t kmer, size_t kmer_size);
+
+/**
+ * decode nucleotide kmer to human-readable string
+ * @param kmer
+ * @param kmer_size
+ * @return
+ */
+template<typename KmerType>
+std::string decode_kmer_nt4(KmerType kmer, size_t kmer_size);
+
+template<>
+std::string decode_kmer_nt4<uint64_t>(uint64_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_nt4<uint32_t>(uint32_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_nt4<uint16_t>(uint16_t kmer, size_t kmer_size);
+
+/**
+ * decode amino acids kmer to human-readable string
+ * @param kmer
+ * @param kmer_size
+ * @return
+ */
+template<typename KmerType>
+std::string decode_kmer_aa(KmerType kmer, size_t kmer_size);
+
+template<>
+std::string decode_kmer_aa<uint64_t>(uint64_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_aa<uint32_t>(uint32_t kmer, size_t kmer_size);
+template<>
+std::string decode_kmer_aa<uint16_t>(uint16_t kmer, size_t kmer_size);
+
+
+} // namespace htio2
+
+#endif /* HTIO2_KMER_H */
+
diff --git a/src/htio2/MT19937.cpp b/src/htio2/MT19937.cpp
new file mode 100644
index 0000000..8bab239
--- /dev/null
+++ b/src/htio2/MT19937.cpp
@@ -0,0 +1,270 @@
+/*
+ A C-program for MT19937-64 (2014/2/23 version).
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ This is a 64-bit version of Mersenne Twister pseudorandom number
+ generator.
+
+ Before using, initialize the state by using init_genrand64(seed)
+ or init_by_array64(init_key, key_length).
+
+ Copyright (C) 2004, 2014, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ References:
+ T. Nishimura, ``Tables of 64-bit Mersenne Twisters''
+ ACM Transactions on Modeling and
+ Computer Simulation 10. (2000) 348--357.
+ M. Matsumoto and T. Nishimura,
+ ``Mersenne Twister: a 623-dimensionally equidistributed
+ uniform pseudorandom number generator''
+ ACM Transactions on Modeling and
+ Computer Simulation 8. (Jan. 1998) 3--30.
+
+ Any feedback is very welcome.
+ http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)
+*/
+
+
+#include "MT19937.h"
+
+#include "JUCE-3.0.8/JuceHeader.h"
+#include <stdio.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <errno.h>
+
+using namespace std;
+using namespace htio2::juce;
+
+#define MM 156
+#define MATRIX_A 0xB5026F5AA96619E9ull
+#define UM 0xFFFFFFFF80000000ull /* Most significant 33 bits */
+#define LM 0x7FFFFFFFull /* Least significant 31 bits */
+
+namespace htio2
+{
+
+uint64_t _get_seed_from_time_()
+{
+ return Time::getCurrentTime().toMilliseconds();
+}
+
+uint64_t _get_seed_from_pid_()
+{
+ uint32_t pid = uint32_t(getpid());
+ uint32_t ppid = uint32_t(getppid());
+ uint64_t result = pid;
+ result <<= 32;
+ result += ppid;
+ return result;
+}
+
+#define RAND_DEV "/dev/urandom"
+
+void _get_seed_from_dev_random_(uint64_t* seeds, size_t len)
+{
+ FILE* fh = fopen(RAND_DEV, "rb");
+ if (!fh)
+ {
+ fprintf(stderr, "ERROR: MT19937 failed to open %s: %s\n",
+ RAND_DEV, strerror(errno));
+ abort();
+ }
+
+
+ if (fread(seeds, sizeof(uint64_t), len, fh) != len)
+ {
+ fprintf(stderr, "ERROR: MT19937 failed to read %s\n", RAND_DEV);
+ abort();
+ }
+}
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+void _get_seed_from_rand_s_(uint64_t* seeds, size_t len)
+{
+ for (size_t i = 0; i < len; i++)
+ rand_s(&seeds[i]);
+}
+#endif
+
+MT19937::MT19937()
+{
+ static bool has_dev_random = true;
+ if (has_dev_random)
+ {
+ File path_dev_random("/dev/random");
+ if (path_dev_random.existsAsFile())
+ {
+ uint64_t seeds[4];
+ _get_seed_from_dev_random_(seeds, 4);
+ set_seed_array(seeds, 4);
+ }
+ else
+ {
+ has_dev_random = false;
+ }
+ }
+
+ if (!has_dev_random)
+ {
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ uint64_t seeds[4];
+ _get_seed_from_rand_s_(seeds, 4);
+ set_seed_array(seeds, 4);
+#else
+ uint64_t seeds[2];
+ seeds[0] = _get_seed_from_time_();
+ seeds[1] = _get_seed_from_pid_();
+ set_seed_array(seeds, 2);
+#endif
+ }
+}
+
+MT19937::MT19937(uint64_t seed)
+{
+ set_seed(seed);
+}
+
+MT19937::MT19937(uint64_t *seed_array, size_t len)
+{
+ set_seed_array(seed_array, len);
+}
+
+void MT19937::set_seed(uint64_t seed)
+{
+ mt[0] = seed;
+ for (mti=1; mti<NN; mti++)
+ mt[mti] = (6364136223846793005ull * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
+}
+
+void MT19937::set_seed_array(uint64_t *seed_array, size_t len)
+{
+ unsigned int i, j;
+ uint64_t k;
+ set_seed(19650218ull);
+ i=1; j=0;
+ k = (NN > len ? NN : len);
+ for (; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ull))
+ + seed_array[j] + j; /* non linear */
+ i++; j++;
+ if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
+ if (j>=len) j=0;
+ }
+ for (k=NN-1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ull))
+ - i; /* non linear */
+ i++;
+ if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
+ }
+
+ mt[0] = 1ull << 63; /* MSB is 1; assuring non-zero initial array */
+}
+
+bool MT19937::next_bool()
+{
+ return next_uint64() > 0x7fffffffffffffffuLL;
+}
+
+uint64_t MT19937::next_uint64()
+{
+ int i;
+ uint64_t x;
+ static uint64_t mag01[2]={0ull, MATRIX_A};
+
+ if (mti >= NN) { /* generate NN words at one time */
+
+ /* if init_genrand64() has not been called, */
+ /* a default initial seed is used */
+ if (mti == NN+1)
+ set_seed(5489ull);
+
+ for (i=0;i<NN-MM;i++) {
+ x = (mt[i]&UM)|(mt[i+1]&LM);
+ mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[int(x & 1ull)];
+ }
+ for (;i<NN-1;i++) {
+ x = (mt[i]&UM)|(mt[i+1]&LM);
+ mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[int(x & 1ull)];
+ }
+ x = (mt[NN-1]&UM)|(mt[0]&LM);
+ mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[int(x & 1ull)];
+
+ mti = 0;
+ }
+
+ x = mt[mti++];
+
+ x ^= (x >> 29) & 0x5555555555555555ull;
+ x ^= (x << 17) & 0x71D67FFFEDA60000ull;
+ x ^= (x << 37) & 0xFFF7EEE000000000ull;
+ x ^= (x >> 43);
+
+ return x;
+}
+
+uint64_t MT19937::next_uint64_in_range(uint64_t upper)
+{
+ uint64_t max64 = std::numeric_limits<uint64_t>::max();
+ uint64_t raw_upper = max64 - max64 % upper;
+
+ for (;;)
+ {
+ uint64_t re = next_uint64();
+ if (re < raw_upper)
+ {
+ return re % upper;
+ }
+ }
+}
+
+int64_t MT19937::next_int63()
+{
+ return (int64_t)(next_uint64() >> 1);
+}
+
+double MT19937::next_double_yy()
+{
+ return (next_uint64() >> 11) * (1.0/9007199254740991.0);
+}
+
+double MT19937::next_double_yn()
+{
+ return (next_uint64() >> 11) * (1.0/9007199254740992.0);
+}
+
+double MT19937::next_double_nn()
+{
+ return ((next_uint64() >> 12) + 0.5) * (1.0/4503599627370496.0);
+}
+
+} // namespace htio2
diff --git a/src/htio2/MT19937.h b/src/htio2/MT19937.h
new file mode 100644
index 0000000..1bcd4c1
--- /dev/null
+++ b/src/htio2/MT19937.h
@@ -0,0 +1,97 @@
+/*
+ A C-program for MT19937-64 (2014/2/23 version).
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ This is a 64-bit version of Mersenne Twister pseudorandom number
+ generator.
+
+ Before using, initialize the state by using init_genrand64(seed)
+ or init_by_array64(init_key, key_length).
+
+ Copyright (C) 2004, 2014, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ References:
+ T. Nishimura, ``Tables of 64-bit Mersenne Twisters''
+ ACM Transactions on Modeling and
+ Computer Simulation 10. (2000) 348--357.
+ M. Matsumoto and T. Nishimura,
+ ``Mersenne Twister: a 623-dimensionally equidistributed
+ uniform pseudorandom number generator''
+ ACM Transactions on Modeling and
+ Computer Simulation 8. (Jan. 1998) 3--30.
+
+ Any feedback is very welcome.
+ http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)
+*/
+#ifndef HTIO2_MT19937_H
+#define HTIO2_MT19937_H
+
+
+#include <stdint.h>
+#include "htio2/RefCounted.h"
+
+namespace htio2
+{
+
+#define NN 312
+
+class MT19937: public RefCounted
+{
+ friend class ::TestFramework;
+public:
+ typedef SmartPtr<MT19937> Ptr;
+ typedef SmartPtr<const MT19937> ConstPtr;
+
+public:
+ MT19937();
+ MT19937(uint64_t seed);
+ MT19937(uint64_t* seed_array, size_t len);
+
+ void set_seed(uint64_t seed);
+ void set_seed_array(uint64_t* seed_array, size_t len);
+
+ bool next_bool();
+ uint64_t next_uint64();
+ uint64_t next_uint64_in_range(uint64_t upper);
+ int64_t next_int63();
+ double next_double_yy();
+ double next_double_yn();
+ double next_double_nn();
+
+protected:
+ uint64_t mt[NN];
+ int mti = NN + 1;
+}; // class MT19937
+
+} // namespace htio2
+
+#endif // HTIO2_MT19937_H
diff --git a/src/htio2/OptionParser.cpp b/src/htio2/OptionParser.cpp
new file mode 100644
index 0000000..066ee2a
--- /dev/null
+++ b/src/htio2/OptionParser.cpp
@@ -0,0 +1,609 @@
+#include "htio2/OptionParser.h"
+#include "htio2/StringUtil.h"
+
+
+#include <limits>
+#include <cstdio>
+
+#if defined _WIN32 || defined _WIN64
+#include <windows.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+using namespace std;
+
+namespace htio2
+{
+
+size_t get_terminal_width()
+{
+#if defined _WIN32 || defined _WIN64
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
+ size_t columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
+ return columns;
+#else
+ struct winsize win_size;
+ ioctl(fileno(stdout), TIOCGWINSZ, &win_size);
+ return win_size.ws_col;
+#endif
+}
+
+void _break_desc_lines_(const string& input, size_t line_size, vector<string>& output)
+{
+ vector<string> paragraphs;
+ htio2::split(input, '\n', paragraphs);
+
+
+
+ for (size_t line_i = 0; line_i < paragraphs.size(); line_i++)
+ {
+ output.push_back(string());
+ const string& para = paragraphs[line_i];
+ vector<string> tokens;
+ htio2::split(para, ' ', tokens);
+
+ for (size_t i_token = 0; i_token < tokens.size(); i_token++)
+ {
+ const string& token = tokens[i_token];
+ if (output.back().size() + token.size() + 1 > line_size)
+ output.push_back(string());
+ if (output.back().length())
+ output.back() += " ";
+ output.back() += token;
+ }
+ }
+}
+
+
+ValueLimit::ValueLimit(size_t min, size_t max)
+ : min(min)
+ , max(max) {}
+
+ValueLimit ValueLimit::Fixed(size_t num)
+{
+ return ValueLimit(num, num);
+}
+
+ValueLimit ValueLimit::Ranged(size_t min, size_t max)
+{
+ return ValueLimit(min, max);
+}
+
+ValueLimit ValueLimit::Free()
+{
+ return ValueLimit(0, numeric_limits<size_t>::max());
+}
+
+Option::ValueBase::ValueBase(ValueLimit limit): limit(limit) {}
+
+
+Option::ValueBase::~ValueBase() {}
+
+Option::BoolSwitch::BoolSwitch(bool *value)
+ : ValueBase(ValueLimit(0,0))
+ , value(value) {}
+
+Option::BoolSwitch::~BoolSwitch() {}
+
+
+bool Option::BoolSwitch::cast_values(const std::vector<string> &values)
+{
+ if (values.size())
+ abort();
+ *value = true;
+ return true;
+}
+
+string Option::BoolSwitch::to_string()
+{
+ return "";
+}
+
+Option::~Option()
+{
+ delete store;
+}
+
+string Option::format_doc(size_t w_line, size_t w_key_left, size_t w_key, size_t w_key_right) const
+{
+ // validate key width
+ string doc_key = format_doc_key();
+
+ int32_t w_key_remain = w_key - doc_key.size();
+ if (w_key_remain < 0)
+ {
+ fprintf(stderr, "option key exceeds width limit %lu: %lu\n%s\n",
+ w_key, doc_key.size(), doc_key.c_str());
+ abort();
+ }
+
+ // get desc with default value
+ string full_desc;
+ string default_value_str = store->to_string();
+ if (default_value_str.length())
+ full_desc = "[" + default_value_str + "] " + option_desc;
+ else
+ full_desc = option_desc;
+
+ // format document
+ string result;
+ if (w_key_left + w_key + w_key_right > w_line / 2)
+ {
+ // key is too wide, put desc in new line
+ result = string(w_key_left, ' ') + doc_key + "\n";
+
+ vector<string> desc_lines;
+ _break_desc_lines_(full_desc, w_line - 4, desc_lines);
+
+ for (size_t i = 0; i < desc_lines.size(); i++)
+ {
+ result += " " + desc_lines[i] + "\n";
+ }
+ }
+ else
+ {
+ vector<string> desc_lines;
+ _break_desc_lines_(full_desc, w_line - w_key_left - w_key - w_key_right, desc_lines);
+
+ string leading_space(w_key_left + w_key + w_key_right, ' ');
+
+ for (size_t i = 0; i < desc_lines.size(); i++)
+ {
+ if (i == 0)
+ {
+ result += string(w_key_left, ' ') + doc_key + string(w_key_remain, ' ') + string(w_key_right, ' ');
+ }
+ else
+ {
+ result += leading_space;
+ }
+ result += desc_lines[i] + "\n";
+ }
+ }
+
+ return result;
+}
+
+
+string Option::format_doc_key() const
+{
+ string result;
+ if (name_short)
+ {
+ result.push_back('-');
+ result.push_back(name_short);
+ }
+ if (name_long.length())
+ {
+ if (result.length())
+ result += "|";
+ result += "--" + name_long;
+ }
+ if (value_desc.length())
+ {
+ if (result.length())
+ result += " ";
+ result += value_desc;
+ }
+ return result;
+}
+
+bool OptionParser::add_option(Option& option)
+{
+ bool long_inserted = false;
+ bool short_inserted = false;
+
+ size_t idx = options.size();
+
+ if (option.name_long.size())
+ {
+ long_inserted = options_by_long.insert(make_pair(option.name_long, idx)).second;
+ }
+
+ if (option.name_short)
+ {
+ short_inserted = options_by_short.insert(make_pair(option.name_short, idx)).second;
+ }
+
+ if (long_inserted || short_inserted)
+ {
+ options.push_back(&option);
+
+ const string& group = option.group;
+ size_t id = group_id_seed++;
+
+ group_ids.insert(make_pair(group, id));
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+typedef pair<int, string> IndexedValue;
+typedef vector<IndexedValue> IndexedValueGroup;
+typedef map<Option*, vector<IndexedValueGroup> > OptionValueMap;
+
+int _groups_sum_(const vector<IndexedValueGroup>& groups)
+{
+ int re = 0;
+ for (size_t i = 0; i < groups.size(); i++)
+ {
+ re += groups[i].size();
+ }
+ return re;
+}
+
+inline void _dump_value_group_(OptionValueMap& store, Option* option, IndexedValueGroup& values)
+{
+ store[option].push_back(values);
+ values.clear();
+}
+
+void OptionParser::parse_options(int& argc, char** argv)
+{
+ //
+ // collect values by option
+ //
+ OptionValueMap values_by_option;
+ {
+ Option* curr_option = NULL;
+ IndexedValueGroup curr_value_group;
+ for (int i = 1; i < argc; i++)
+ {
+ string curr_token((argv)[i]);
+
+ // token is option key
+ if (curr_token[0] == '-' && curr_token.length() >= 2)
+ {
+ // long key in "--xxx" style
+ if (curr_token[1] == '-')
+ {
+ // clear previous values
+ _dump_value_group_(values_by_option, curr_option, curr_value_group);
+
+ // find option object
+ curr_option = find_option_long(curr_token);
+ }
+
+ // short key in "-x" style
+ else
+ {
+ // clear previous values
+ _dump_value_group_(values_by_option, curr_option, curr_value_group);
+
+ // find option object
+ curr_option = find_option_short(curr_token[1]);
+
+ // short key contains a value
+ if (curr_token.length() > 2)
+ {
+ string curr_token_value = curr_token.substr(2);
+
+ // extra check for that the option must accept value
+ if (curr_option->store->limit.max == 0)
+ {
+ fprintf(stderr, "ERROR: option -%c is bool switch, but a value \"%s\" is given via \"%s\"\n",
+ curr_option->name_short, curr_token_value.c_str(), curr_token.c_str());
+ exit(EXIT_FAILURE);
+ }
+
+ curr_value_group.push_back(make_pair(i, curr_token_value));
+ }
+ }
+ }
+ // token is not key
+ else
+ {
+ curr_value_group.push_back(make_pair(i, curr_token));
+ }
+ } // argv cycle
+
+ // lasting...
+ _dump_value_group_(values_by_option, curr_option, curr_value_group);
+ }
+
+ //
+ // set option values
+ //
+ vector<int> unused_indices;
+ for (OptionValueMap::iterator it = values_by_option.begin();
+ it != values_by_option.end();
+ ++it)
+ {
+ Option* option = it->first;
+ vector<IndexedValueGroup>& value_groups = it->second;
+
+ if (option)
+ {
+ vector<string> values_plain;
+
+ // a bool switch option, accept no values
+ if (option->store->limit.max == 0)
+ {
+ // it should appear only once
+ if (value_groups.size() > 1)
+ {
+ fprintf(stderr, "ERROR: bool switch option \"%s\" appeared more than once\n",
+ option->format_doc_key().c_str());
+ exit(EXIT_FAILURE);
+ }
+
+ // all values are unused
+ for (size_t i_group = 0; i_group < value_groups.size(); i_group++)
+ {
+ const IndexedValueGroup& value_group = value_groups[i_group];
+ for (size_t i_value = 0; i_value < value_group.size(); i_value++)
+ {
+ unused_indices.push_back(value_group[i_value].first);
+ }
+ }
+ }
+ // accept one value
+ else if (option->store->limit.min == 1 && option->store->limit.max == 1)
+ {
+ // it should appear only once
+ if (value_groups.size() > 1)
+ {
+ fprintf(stderr, "ERROR: single value option \"%s\" appeared more than once\n",
+ option->format_doc_key().c_str());
+ exit(EXIT_FAILURE);
+ }
+
+ const IndexedValueGroup& first_group = value_groups[0];
+
+ // we should have value
+ if (!first_group.size())
+ {
+ fprintf(stderr, "ERROR: single value option \"%s\" has no value\n",
+ option->format_doc_key().c_str());
+ exit(EXIT_FAILURE);
+ }
+
+ // first value is used, all following values are unused
+ for (size_t i_value = 0; i_value < first_group.size(); i_value++)
+ {
+ if (i_value == 0)
+ values_plain.push_back(first_group[i_value].second);
+ else
+ unused_indices.push_back(first_group[i_value].first);
+ }
+ }
+ // accept variable number of values
+ else
+ {
+ const char* TEMPLATE_LOWER_THAN_MIN = 0;
+ if (option->store->limit.min == option->store->limit.max)
+ TEMPLATE_LOWER_THAN_MIN = "ERROR: option \"%s\" requires %lu values, but only %lu got\n";
+ else
+ TEMPLATE_LOWER_THAN_MIN = "ERROR: option \"%s\" requires %lu values at least, but only %lu got\n";
+
+ // option can occur multiple times
+ if (option->flags & Option::FLAG_MULTI_KEY)
+ {
+ for (size_t i_group = 0; i_group < value_groups.size(); i_group++)
+ {
+ const IndexedValueGroup& value_group = value_groups[i_group];
+ for (size_t i_value = 0; i_value < value_group.size(); i_value++)
+ {
+ if (values_plain.size() < option->store->limit.max)
+ values_plain.push_back(value_group[i_value].second);
+ else
+ unused_indices.push_back(value_group[i_value].first);
+ }
+ }
+
+ // validate value number
+ if (values_plain.size() < option->store->limit.min)
+ {
+ fprintf(stderr, TEMPLATE_LOWER_THAN_MIN,
+ option->format_doc_key().c_str(), option->store->limit.min, values_plain.size());
+ exit(EXIT_FAILURE);
+ }
+ }
+ // option can occur only once
+ else
+ {
+ if (value_groups.size() > 1)
+ {
+ fprintf(stderr, "ERROR: multi value option \"%s\" appeared more than once\n",
+ option->format_doc_key().c_str());
+ exit(EXIT_FAILURE);
+ }
+
+ const IndexedValueGroup& first_group = value_groups[0];
+
+ // validate value number
+ if (first_group.size() < option->store->limit.min)
+ {
+
+ fprintf(stderr, TEMPLATE_LOWER_THAN_MIN,
+ option->format_doc_key().c_str(), option->store->limit.min, first_group.size());
+ exit(EXIT_FAILURE);
+ }
+
+ // store
+ for (size_t i_value = 0; i_value < first_group.size(); i_value++)
+ {
+ if (i_value < option->store->limit.max)
+ values_plain.push_back(first_group[i_value].second);
+ else
+ unused_indices.push_back(first_group[i_value].first);
+ }
+ }
+ }
+
+ if (!option->store->cast_values(values_plain))
+ {
+ fprintf(stderr, "ERROR: failed to cast values for option \"%s\"\n",
+ option->format_doc_key().c_str());
+ for (size_t i = 0; i < values_plain.size(); i++)
+ {
+ fprintf(stderr, "ERROR: \"%s\"\n",
+ values_plain[i].c_str());
+ }
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ // ungrouped options, collect to unused
+ for (size_t i_group = 0; i_group < value_groups.size(); i_group++)
+ {
+ const IndexedValueGroup& value_group = value_groups[i_group];
+ for (size_t i_value = 0; i_value < value_group.size(); i_value++)
+ {
+ unused_indices.push_back(value_group[i_value].first);
+ }
+ }
+ }
+ } // option cycle
+
+ // modify argument
+ // collect unprocessed names
+ vector<char*> buffer;
+ for (size_t i = 0; i < unused_indices.size(); i++)
+ {
+ int index = unused_indices[i];
+ if (index > 0)
+ buffer.push_back(argv[index]);
+ }
+
+ // modify argv
+ for (size_t i = 1; i < argc; i++)
+ {
+ if (i <= buffer.size())
+ {
+ argv[i] = buffer[i-1];
+ }
+ else
+ {
+ argv[i] = NULL;
+ }
+ }
+
+ argc = buffer.size() + 1;
+}
+
+Option* OptionParser::find_option_long(const string &key)
+{
+ string key_use = key.substr(2);
+
+ // find exact key
+ map<string, size_t>::iterator it = options_by_long.find(key_use);
+ if (it != options_by_long.end())
+ return options[it->second];
+
+ // find by prefix
+ vector<string> matched_keys;
+ vector<size_t> matched_i;
+
+ for (it = options_by_long.begin(); it != options_by_long.end(); it++)
+ {
+ const string& curr_key = it->first;
+
+ if (curr_key.find(key_use) == 0)
+ {
+ matched_keys.push_back("--"+curr_key);
+ matched_i.push_back(it->second);
+ }
+ }
+
+ if (matched_keys.size() == 0)
+ {
+ fprintf(stderr, "ERROR: unknown option \"%s\"\n", key.c_str());
+ exit(EXIT_FAILURE);
+ }
+ else if (matched_keys.size() == 1)
+ {
+ return options[matched_i[0]];
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: ambiguous option prefix \"%s\", which matches:\n", key.c_str());
+ for (size_t i = 0; i < matched_keys.size(); i++)
+ fprintf(stderr, "ERROR: %s\n", matched_keys[i].c_str());
+ exit(EXIT_FAILURE);
+ }
+}
+
+Option* OptionParser::find_option_short(char key)
+{
+ std::map<char, size_t>::iterator it = options_by_short.find(key);
+ if (it != options_by_short.end())
+ return options[it->second];
+ else
+ {
+ fprintf(stderr, "ERROR: unknown option \"-%c\"\n", key);
+ exit(EXIT_FAILURE);
+ }
+}
+
+struct GroupSort
+{
+ GroupSort(std::map<std::string, size_t>& ids): ids(ids) {}
+
+ bool operator () (const string& a, const string& b)
+ {
+ return ids[a] < ids[b];
+ }
+
+ std::map<std::string, size_t>& ids;
+};
+
+string OptionParser::format_document()
+{
+ size_t line_width = get_terminal_width();
+
+ // categorize by group
+ map<string, vector<Option*> > groups;
+ for (size_t i=0; i<options.size(); i++)
+ {
+ const string& group_name = options[i]->group;
+ groups[group_name].push_back(options[i]);
+ }
+
+ string result;
+
+ // get key length
+ size_t max_doc_key_len = 0;
+
+ for (size_t i = 0; i < options.size(); i++)
+ {
+ Option* opt = options[i];
+ string doc_key = opt->format_doc_key();
+ if (max_doc_key_len < doc_key.length())
+ max_doc_key_len = doc_key.length();
+ }
+
+ // sort groups by their occurance
+ vector<string> group_names;
+ for (pair<string, size_t> value : group_ids)
+ group_names.push_back(value.first);
+
+ sort(group_names.begin(), group_names.end(), GroupSort(group_ids));
+
+ // format document for each option group
+ for (const string& group_name : group_names)
+ {
+ vector<Option*>& group_options = groups[group_name];
+
+ if (group_name.length())
+ result += group_name + "\n\n";
+
+ for (size_t i = 0; i < group_options.size(); i++)
+ {
+ Option* opt = group_options[i];
+ result += opt->format_doc(line_width, 2, max_doc_key_len, 2);
+ result += "\n";
+ }
+ }
+
+ return result;
+}
+
+} // namespace tcrk2
diff --git a/src/htio2/OptionParser.h b/src/htio2/OptionParser.h
new file mode 100644
index 0000000..1b28b9a
--- /dev/null
+++ b/src/htio2/OptionParser.h
@@ -0,0 +1,231 @@
+#ifndef HTIO2_OPTION_PARSER
+#define HTIO2_OPTION_PARSER
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <cstdio>
+#include <cstdlib>
+#include <stdint.h>
+
+#include "htio2/RefCounted.h"
+#include "htio2/Cast.h"
+
+namespace htio2
+{
+
+class OptionParser;
+class Option;
+
+class ValueLimit
+{
+ friend class OptionParser;
+ friend class Option;
+
+ ValueLimit(size_t min, size_t max);
+
+public:
+ static ValueLimit Fixed(size_t num);
+ static ValueLimit Ranged(size_t min, size_t max);
+ static ValueLimit Free();
+
+protected:
+ size_t min;
+ size_t max;
+};
+
+class Option
+{
+ friend class OptionParser;
+
+public:
+ enum OptionFlag
+ {
+ FLAG_NONE = 0,
+ FLAG_MULTI_KEY = 1,
+ };
+
+protected:
+ struct ValueBase
+ {
+ ValueBase(ValueLimit limit);
+ virtual ~ValueBase();
+ virtual bool cast_values(const std::vector<std::string>& values) = 0;
+ virtual std::string to_string() = 0;
+
+ ValueLimit limit;
+ };
+
+ struct BoolSwitch: public ValueBase
+ {
+ BoolSwitch(bool* value);
+ virtual ~BoolSwitch();
+
+ virtual bool cast_values(const std::vector<std::string>& values);
+ virtual std::string to_string();
+
+ bool* value;
+ };
+
+ template<typename T>
+ struct SingleValue: public ValueBase
+ {
+ SingleValue(T* value)
+ : ValueBase(ValueLimit(1,1))
+ , value(value) {}
+ virtual ~SingleValue() {}
+
+ virtual bool cast_values(const std::vector<std::string>& values)
+ {
+ if (values.size() != 1)
+ abort();
+ return htio2::from_string<T>(values[0], *value);
+ }
+
+ virtual std::string to_string()
+ {
+ return htio2::to_string<T>(*value);
+ }
+
+
+ T* value;
+ };
+
+ template<typename T>
+ struct MultiValue: public ValueBase
+ {
+ MultiValue(std::vector<T>* values, ValueLimit limit)
+ : ValueBase(limit)
+ , value_list(values) {}
+
+
+ virtual bool cast_values(const std::vector<std::string>& values)
+ {
+ for (size_t i = 0; i < values.size(); i++)
+ {
+ T tmp;
+ if (!from_string<T>(values[i], tmp))
+ return false;
+ value_list->push_back(tmp);
+ }
+ return true;
+ }
+
+ virtual std::string to_string()
+ {
+ std::string result;
+ for (size_t i = 0; i < value_list->size(); i++)
+ {
+ if (i > 0) result += " ";
+ result += htio2::to_string((*value_list)[i]);
+ }
+ return result;
+ }
+
+ std::vector<T>* value_list;
+ };
+
+public:
+ Option(const std::string& name_long,
+ char name_short,
+ const std::string& group,
+ bool* value_store,
+ int32_t flags,
+ const std::string& option_desc)
+ : name_long(name_long)
+ , name_short(name_short)
+ , group(group)
+ , store(new BoolSwitch(value_store))
+ , flags(flags)
+ , option_desc(option_desc)
+ , value_desc("")
+ {
+ }
+
+ template<typename T>
+ Option(const std::string& name_long,
+ char name_short,
+ const std::string& group,
+ T* value_store,
+ int32_t flags,
+ const std::string& option_desc,
+ const std::string& value_desc)
+ : name_long(name_long)
+ , name_short(name_short)
+ , group(group)
+ , store(new SingleValue<T>(value_store))
+ , flags(flags)
+ , option_desc(option_desc)
+ , value_desc(value_desc)
+ {
+ }
+
+ template<typename T>
+ Option(const std::string& name_long,
+ char name_short,
+ const std::string& group,
+ std::vector<T>* value_store,
+ int32_t flags,
+ ValueLimit value_num_limit,
+ const std::string& option_desc,
+ const std::string& value_desc)
+ : name_long(name_long)
+ , name_short(name_short)
+ , group(group)
+ , store(new MultiValue<T>(value_store, value_num_limit))
+ , flags(flags)
+ , option_desc(option_desc)
+ , value_desc(value_desc)
+ {
+ }
+
+ virtual ~Option();
+
+private:
+ Option(const Option& other);
+ Option& operator = (const Option& other);
+
+protected:
+ static bool validate_name(char name);
+ static bool validate_name(const std::string& name);
+ std::string format_doc(size_t w_line, size_t w_key_left, size_t w_key, size_t w_key_right) const;
+ std::string format_doc_key() const;
+
+protected:
+ std::string name_long;
+ char name_short;
+ std::string group;
+ ValueBase* store = nullptr;
+ uint32_t flags = 0;
+ std::string option_desc;
+ std::string value_desc;
+};
+
+
+class OptionParser: public htio2::RefCounted
+{
+public:
+ typedef SmartPtr<OptionParser> Ptr;
+ typedef SmartPtr<const OptionParser> ConstPtr;
+
+public:
+ bool add_option(Option& option);
+ void parse_options(int& argc, char** argv);
+ std::string format_document();
+
+protected:
+ Option* find_option_long(const std::string& key);
+ Option* find_option_short(char key);
+
+protected:
+ size_t group_id_seed = 0;
+ std::map<std::string, size_t> group_ids;
+ std::vector<Option*> options;
+ std::map<char, size_t> options_by_short;
+ std::map<std::string, size_t> options_by_long;
+};
+
+} // namespace htio2
+
+#endif // HTIO2_OPTION_PARSER
diff --git a/src/htio2/PairedEndIO.cpp b/src/htio2/PairedEndIO.cpp
new file mode 100644
index 0000000..ecd5299
--- /dev/null
+++ b/src/htio2/PairedEndIO.cpp
@@ -0,0 +1,206 @@
+/*
+ * File: PairedEndIO.cpp
+ * Author: yangxi
+ *
+ * Created on March 27, 2014, 9:15 AM
+ */
+
+#include "htio2/PairedEndIO.h"
+
+#include "htio2/Error.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FastaIO.h"
+
+using namespace std;
+
+namespace htio2
+{
+
+PairedEndIO::PairedEndIO(const std::string& file,
+ IOMode mode,
+ Strand strand_r1_in_file,
+ Strand strand_r2_in_file,
+ CompressFormat comp,
+ SeqFormat format)
+: fh1(0)
+, fh2(0)
+, interleave(true)
+, strand_r1_in_file(strand_r1_in_file)
+, strand_r2_in_file(strand_r2_in_file)
+{
+ switch (format)
+ {
+ case FORMAT_FASTQ:
+ fh1 = new FastqIO(file, mode, comp);
+ break;
+ case FORMAT_FASTA:
+ fh1 = new FastaIO(file, mode, comp);
+ break;
+ default:
+ fh1 = SeqIO::New(file, mode, comp);
+ break;
+ }
+}
+
+PairedEndIO::PairedEndIO(const std::string& file1,
+ const std::string& file2,
+ IOMode mode,
+ Strand strand_r1_in_file,
+ Strand strand_r2_in_file,
+ CompressFormat comp,
+ SeqFormat format)
+: fh1(0)
+, fh2(0)
+, interleave(false)
+, strand_r1_in_file(strand_r1_in_file)
+, strand_r2_in_file(strand_r2_in_file)
+{
+ switch (format)
+ {
+ case FORMAT_FASTQ:
+ fh1 = new FastqIO(file1, mode, comp);
+ fh2 = new FastqIO(file2, mode, comp);
+ break;
+ case FORMAT_FASTA:
+ fh1 = new FastaIO(file1, mode, comp);
+ fh2 = new FastaIO(file2, mode, comp);
+ break;
+ default:
+ fh1 = SeqIO::New(file1, mode, comp);
+ fh2 = SeqIO::New(file2, mode, comp);
+ break;
+ }
+}
+
+PairedEndIO::~PairedEndIO()
+{
+ delete fh1;
+ if (fh2) delete fh2;
+}
+
+bool PairedEndIO::next_pair(FastqSeq& seq1,
+ FastqSeq& seq2,
+ Strand strand_r1,
+ Strand strand_r2)
+{
+ if (strand_r1 == strand_r1_in_file)
+ {
+ if (strand_r2 == strand_r2_in_file)
+ {
+ return _read_next_pair(seq1, seq2);
+ }
+ else
+ {
+ bool re = _read_next_pair(seq1, tmp2);
+ if (re)
+ tmp2.revcom(seq2);
+ return re;
+ }
+ }
+ else
+ {
+ if (strand_r2 == strand_r2_in_file)
+ {
+ bool re = _read_next_pair(tmp1, seq2);
+ if (re)
+ tmp1.revcom(seq1);
+ return re;
+ }
+ else
+ {
+ bool re = _read_next_pair(tmp1, tmp2);
+ if (re)
+ {
+ tmp1.revcom(seq1);
+ tmp2.revcom(seq2);
+ }
+ return re;
+ }
+ }
+}
+
+void PairedEndIO::write_pair(const FastqSeq& seq1,
+ const FastqSeq& seq2,
+ Strand strand_r1,
+ Strand strand_r2)
+{
+ if (strand_r1 == strand_r1_in_file)
+ {
+ if (strand_r2 == strand_r2_in_file)
+ {
+ _write_pair(seq1, seq2);
+ }
+ else
+ {
+ seq2.revcom(tmp2);
+ _write_pair(seq1, tmp2);
+ }
+ }
+ else
+ {
+ if (strand_r2 == strand_r2_in_file)
+ {
+ seq1.revcom(tmp1);
+ _write_pair(tmp1, seq2);
+ }
+ else
+ {
+ seq1.revcom(tmp1);
+ seq2.revcom(tmp2);
+ _write_pair(tmp1, tmp2);
+ }
+ }
+}
+
+bool PairedEndIO::_read_next_pair(FastqSeq& seq1, FastqSeq& seq2)
+{
+ if (interleave)
+ {
+ bool re1 = fh1->next_seq(seq1);
+ bool re2 = fh1->next_seq(seq2);
+ if (re1)
+ {
+ if (re2)
+ return true;
+ else
+ throw InvalidFileContent("incomplete interleaved sequence file", fh1->tell());
+ }
+ else
+ return false;
+ }
+ else
+ {
+ bool re1 = fh1->next_seq(seq1);
+ bool re2 = fh2->next_seq(seq2);
+ if (re1)
+ {
+ if (re2)
+ return true;
+ else
+ throw InvalidFileContent("paired-end from two files: file 2 ended, but file 1 not", fh1->tell());
+ }
+ else
+ {
+ if (re2)
+ throw InvalidFileContent("paired-end from two files: file 1 ended, but file 2 not", fh2->tell());
+ else
+ return false;
+ }
+ }
+}
+
+void PairedEndIO::_write_pair(const FastqSeq& seq1, const FastqSeq& seq2)
+{
+ if (interleave)
+ {
+ fh1->write_seq(seq1);
+ fh1->write_seq(seq2);
+ }
+ else
+ {
+ fh1->write_seq(seq1);
+ fh2->write_seq(seq2);
+ }
+}
+
+} // namespace htio2
diff --git a/src/htio2/PairedEndIO.h b/src/htio2/PairedEndIO.h
new file mode 100644
index 0000000..857fa2e
--- /dev/null
+++ b/src/htio2/PairedEndIO.h
@@ -0,0 +1,133 @@
+/*
+ * File: PairedEndIO.h
+ * Author: yangxi
+ *
+ * Created on March 27, 2014, 9:15 AM
+ */
+
+#ifndef HTIO2_PAIRED_END_IO_H
+#define HTIO2_PAIRED_END_IO_H
+
+#include "htio2/RefCounted.h"
+#include "htio2/Enum.h"
+#include "htio2/FastqSeq.h"
+
+namespace htio2
+{
+
+class SeqIO;
+class FastqSeq;
+
+/**
+ * A wrapper class that handle several paired-end reads read/write issues.
+ *
+ * The PairedEndIO class is designed for handle several paired-end related
+ * issues:
+ *
+ * - they are stored in one interleaved file, or two files?
+ * - the strand of the reads are Fwd-Rev (the most common), or Rev-Fwd (common for long insersion libraries)?
+ *
+ * For the first issue, PairedEndIO provides two constructors: one with only one
+ * file parameter, and the other one with two file parameters. If the object is
+ * built with the one-file constructor, it is
+ *
+ * For the second issue, when PairedEndIO is being constructed, it requires the
+ * strand of reads in file being specified; and when read/write sequences, it
+ * require the strand of the sequence object being specified.
+ *
+ * For example, if you specify the reads file is in FWD and REV format (the most
+ * common case), and you specify the reads you get is in FWD and FWD format when
+ * you call next_pair(), read 1 will be given as-is, while read 2 will be
+ * reverse-complemented.
+ */
+class PairedEndIO : public RefCounted
+{
+public:
+ typedef SmartPtr<PairedEndIO> Ptr;
+ typedef SmartPtr<const PairedEndIO> ConstPtr;
+public:
+ /**
+ * create PairedEndIO object. Both ends are stored in one interleaved file.
+ * @param file file for input reads.
+ * @param mode READ/WRITE/APPEND.
+ * @param strand_r1_in_file strand of read 1 in file.
+ * @param strand_r2_in_file strand of read 2 in file.
+ * @param comp compression format. COMPRESS_UNKNOWN for automatically guess by file name.
+ * @param format sequence format. FORMAT_UNKNOWN for automatically guess by file name and/or content.
+ */
+ PairedEndIO(const std::string& file,
+ IOMode mode,
+ Strand strand_r1_in_file = STRAND_FWD,
+ Strand strand_r2_in_file = STRAND_REV,
+ CompressFormat comp = COMPRESS_UNKNOWN,
+ SeqFormat format = FORMAT_UNKNOWN);
+
+ /**
+ * create PairedEndIO object. Two read ends are stored in two separate file.
+ * @param file1 file for read 1.
+ * @param file2 file for read 2.
+ * @param mode READ/WRITE/APPEND.
+ * @param strand_r1_in_file strand of read 1 in file.
+ * @param strand_r2_in_file strand of read 2 in file.
+ * @param comp compression format. COMPRESS_UNKNOWN for automatically guess by file name.
+ * @param format sequence format. FORMAT_UNKNOWN for automatically guess by file name and/or content.
+ */
+ PairedEndIO(const std::string& file1,
+ const std::string& file2,
+ IOMode mode,
+ Strand strand_r1_in_file = STRAND_FWD,
+ Strand strand_r2_in_file = STRAND_REV,
+ CompressFormat comp = COMPRESS_UNKNOWN,
+ SeqFormat format = FORMAT_UNKNOWN);
+
+ virtual ~PairedEndIO();
+
+ /**
+ * read one pair from file
+ * @param seq1
+ * @param seq2
+ * @param strand_r1 strand of read 1 you expect to get
+ * @param strand_r2 strand of read 2 you expect to get
+ * @return false if reached end of file, otherwise true.
+ */
+ bool next_pair(FastqSeq& seq1,
+ FastqSeq& seq2,
+ Strand strand_r1 = STRAND_FWD,
+ Strand strand_r2 = STRAND_FWD);
+
+ /**
+ *
+ * @param seq1 read 1 to be written
+ * @param seq2 read 2 to be written
+ * @param strand_r1 strand of read 1 you give
+ * @param strand_r2 strand of read 2 you give
+ */
+ void write_pair(const FastqSeq& seq1,
+ const FastqSeq& seq2,
+ Strand strand_r1 = STRAND_FWD,
+ Strand strand_r2 = STRAND_FWD);
+
+protected:
+ SeqIO* fh1;
+ SeqIO* fh2;
+
+ FastqSeq tmp1;
+ FastqSeq tmp2;
+
+ Strand strand_r1_in_file;
+ Strand strand_r2_in_file;
+ bool interleave;
+
+private:
+ bool _read_next_pair(FastqSeq& seq1, FastqSeq& seq2);
+ void _write_pair(const FastqSeq& seq1, const FastqSeq& seq2);
+
+ PairedEndIO(const PairedEndIO& orig);
+ PairedEndIO& operator =(const PairedEndIO& orig);
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_PAIRED_END_IO_H */
+
+
diff --git a/src/htio2/PlainFileHandle.cpp b/src/htio2/PlainFileHandle.cpp
new file mode 100644
index 0000000..d9ebf35
--- /dev/null
+++ b/src/htio2/PlainFileHandle.cpp
@@ -0,0 +1,117 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htio2/PlainFileHandle.h"
+#include <cstring>
+#include <cstdio>
+#include <cerrno>
+#include <stdexcept>
+
+using namespace std;
+
+namespace htio2
+{
+
+PlainFileHandle::PlainFileHandle(const std::string& file, IOMode mode) : auto_close(true)
+{
+ handle = fopen(file.c_str(), get_io_mode_str(mode));
+ if (handle == 0)
+ {
+ const char* msg = strerror(errno);
+ throw runtime_error(string(msg));
+ }
+
+ offset = ftell(handle);
+ curr_chr = fgetc(handle);
+}
+
+PlainFileHandle::PlainFileHandle(FILE* handle, bool auto_close) : handle(handle), auto_close(auto_close)
+{
+ offset = ftell(handle);
+ curr_chr = fgetc(handle);
+}
+
+PlainFileHandle::~PlainFileHandle()
+{
+ if (auto_close) fclose(handle);
+}
+
+bool PlainFileHandle::read_line(std::string& buffer)
+{
+ buffer.clear();
+ if (curr_chr == EOF) return false;
+
+ while (1)
+ {
+ switch (curr_chr)
+ {
+ case EOF:
+ goto END;
+ case LINE_END_CR:
+ curr_chr = fgetc(handle);
+ if (curr_chr == LINE_END_LF) curr_chr = fgetc(handle);
+ goto END;
+ case LINE_END_LF:
+ curr_chr = fgetc(handle);
+ goto END;
+ default:
+ buffer.push_back(curr_chr);
+ curr_chr = fgetc(handle);
+ }
+ }
+
+END:
+ offset = ftell(handle) - 1;
+ return true;
+}
+
+void PlainFileHandle::write_line(const std::string& content)
+{
+ fwrite(content.data(), 1, content.size(), handle);
+ fputc('\n', handle);
+ offset = ftell(handle);
+}
+
+void PlainFileHandle::seek(off_t offset, int whence)
+{
+ if (whence == SEEK_SET)
+ {
+ fseek(handle, offset, SEEK_SET);
+ this->offset = offset;
+ }
+ else if (whence == SEEK_CUR)
+ {
+ fseek(handle, this->offset, SEEK_SET);
+ fseek(handle, offset, SEEK_CUR);
+ this->offset += offset;
+ }
+ else if (whence == SEEK_END)
+ {
+ fseek(handle, 0, SEEK_END);
+ this->offset = ftell(handle) + offset;
+ fseek(handle, offset, SEEK_END);
+ }
+ else
+ throw runtime_error("invalid seek whence");
+
+ curr_chr = fgetc(handle);
+}
+
+off_t PlainFileHandle::tell() const
+{
+ return offset;
+}
+
+} // namespace htio2
diff --git a/src/htio2/PlainFileHandle.h b/src/htio2/PlainFileHandle.h
new file mode 100644
index 0000000..b975344
--- /dev/null
+++ b/src/htio2/PlainFileHandle.h
@@ -0,0 +1,86 @@
+// HTIO - a high-throughput sequencing reads input/output library
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTIO2_PLAIN_FILE_HANDLE_H
+#define HTIO2_PLAIN_FILE_HANDLE_H
+
+#include "htio2/FileHandle.h"
+
+namespace htio2
+{
+
+class PlainFileHandle : public FileHandle
+{
+ friend class ::TestFramework;
+public:
+ typedef SmartPtr<PlainFileHandle> Ptr;
+ typedef SmartPtr<const PlainFileHandle> ConstPtr;
+public:
+ /**
+ * create by file name and mode
+ * @param file file name
+ * @param mode "rb" for read, "wb" for write. See manual of stdio.h for more modes.
+ */
+ PlainFileHandle(const std::string& file, IOMode mode);
+
+ /**
+ * create from C standard file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying FILE will be closed when the object is destroyed
+ */
+ PlainFileHandle(FILE* handle, bool auto_close = true);
+ virtual ~PlainFileHandle();
+
+ /**
+ * Read one line. The end-of-line character can be CR, LF and CRLF.
+ * @param buffer
+ * @return true if get a line, false if reached end of file.
+ */
+ virtual bool read_line(std::string& buffer);
+
+ /**
+ * Write one line. The end-of-line character is decided by the system.
+ * @param content
+ */
+ virtual void write_line(const std::string& content);
+
+ /**
+ * Seek to a file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @param offset
+ * @param whence 0 for absolute, 1 for relative
+ */
+ virtual void seek(off_t offset, int whence);
+
+ /**
+ * Get the current file offset.
+ * The offset can be different with the wrapped FILE* or gzFile's offset.
+ * See implementation of read_line() for detail.
+ * @return offset
+ */
+ virtual off_t tell() const;
+
+private:
+ FILE* handle;
+ bool auto_close;
+ off_t offset;
+ char curr_chr;
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_PLAIN_FILE_HANDLE_H */
+
diff --git a/src/htio2/QualityUtil.cpp b/src/htio2/QualityUtil.cpp
new file mode 100644
index 0000000..5a2330f
--- /dev/null
+++ b/src/htio2/QualityUtil.cpp
@@ -0,0 +1,149 @@
+#include "htio2/QualityUtil.h"
+#include "htio2/Error.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+
+#include <map>
+
+using namespace std;
+
+namespace htio2
+{
+
+QualityEncode guess_quality_encode(char qual_ascii_min, char qual_ascii_max)
+{
+ if (qual_ascii_min > qual_ascii_max)
+ return ENCODE_UNKNOWN;
+
+ if (64 <= qual_ascii_min && qual_ascii_max <= 126)
+ {
+ // 0 to 62, 64 based
+ return ENCODE_ILLUMINA;
+ }
+ else if (59 <= qual_ascii_min && qual_ascii_max <= 126)
+ {
+ // -5 to 62, 64 based
+ return ENCODE_SOLEXA;
+ }
+ else if (33 <= qual_ascii_min && qual_ascii_max <= 74)
+ {
+ // 0 to 41, 33 based
+ return ENCODE_CASAVA_1_8;
+ }
+ else if (33 <= qual_ascii_min && qual_ascii_max <= 126)
+ {
+ // 0 to 93, 33 based
+ return ENCODE_SANGER;
+ }
+ else
+ {
+ return ENCODE_UNKNOWN;
+ }
+}
+
+QualityEncode guess_quality_encode(const std::string& quality)
+{
+ if (!quality.length()) return ENCODE_UNKNOWN;
+
+ char min = quality[0];
+ char max = quality[0];
+
+ for (size_t i = 1; i < quality.length(); i++)
+ {
+ const char curr = quality[i];
+ if (curr < min) min = curr;
+ if (max < curr) max = curr;
+ }
+
+ return guess_quality_encode(min, max);
+}
+
+QualityEncode guess_quality_encode(FastqIO& stream, size_t num_to_guess)
+{
+ FastqSeq seq;
+
+ char min = 127;
+ char max = 0;
+
+ for (size_t i = 0; i < num_to_guess; i++)
+ {
+ if (!stream.next_seq(seq)) break;
+ for (size_t i_qual = 0; i_qual < seq.quality.length(); i_qual++)
+ {
+ const char qual = seq.quality[i_qual];
+ if (qual < min) min = qual;
+ if (max < qual) max = qual;
+ }
+ }
+
+ return guess_quality_encode(min, max);
+}
+
+void get_quality_range(QualityEncode encode, int16_t& qual_from, int16_t& qual_to)
+{
+ if (encode == ENCODE_SANGER)
+ {
+ qual_from = 0;
+ qual_to = 93;
+ }
+ else if (encode == ENCODE_SOLEXA)
+ {
+ qual_from = -5;
+ qual_to = 62;
+ }
+ else if (encode == ENCODE_ILLUMINA)
+ {
+ qual_from = 0;
+ qual_to = 62;
+ }
+ else if (encode == ENCODE_CASAVA_1_8)
+ {
+ qual_from = 0;
+ qual_to = 41;
+ }
+ else
+ {
+ throw InvalidQualityEncode(encode);
+ }
+}
+
+void decode_quality(const std::string& input, std::vector<int16_t>& output, QualityEncode encode)
+{
+ int16_t offset = get_quality_offset(encode);
+ if (offset == -1) throw InvalidQualityEncode(encode);
+
+ const size_t sz = input.size();
+ output.resize(sz);
+ for (size_t i = 0; i < sz; i++)
+ output[i] = input[i] - offset;
+}
+
+void encode_quality(const std::vector<int16_t>& input, std::string& output, QualityEncode encode)
+{
+ int16_t offset = get_quality_offset(encode);
+ if (offset == -1) throw InvalidQualityEncode(encode);
+
+ const size_t sz = input.size();
+ output.resize(sz);
+ for (size_t i = 0; i < sz; i++)
+ output[i] = input[i] + offset;
+}
+
+void recode_quality(const std::string& input, std::string& output, QualityEncode encode_input, QualityEncode encode_output)
+{
+ size_t len = input.length();
+ vector<int16_t> qual_in(len);
+ vector<int16_t> qual_out(len);
+
+ decode_quality(input, qual_in, encode_input);
+
+ for (size_t i = 0; i < len; i++)
+ {
+ float p = quality_to_probability(qual_in[i], encode_input);
+ qual_out[i] = probability_to_quality(p, encode_output);
+ }
+
+ encode_quality(qual_out, output, encode_output);
+}
+
+} // namespace htio2
diff --git a/src/htio2/QualityUtil.h b/src/htio2/QualityUtil.h
new file mode 100644
index 0000000..e8c41bd
--- /dev/null
+++ b/src/htio2/QualityUtil.h
@@ -0,0 +1,150 @@
+/*
+ * File: QualityUtil.h
+ * Author: yangxi
+ *
+ * Created on September 26, 2013, 3:16 PM
+ */
+
+#ifndef HTIO2_QUALITY_UTIL_H
+#define HTIO2_QUALITY_UTIL_H
+
+#include "htio2/Enum.h"
+#include <cmath>
+#include <stdint.h>
+#include <vector>
+
+namespace htio2
+{
+
+class FastqIO;
+
+
+/**
+ * guess quality encode from a range of quality
+ * @param qual_ascii_min minimum quality in ascii
+ * @param qual_ascii_max maximum quality in ascii
+ * @return
+ */
+QualityEncode guess_quality_encode(char qual_ascii_min, char qual_ascii_max);
+
+/**
+ * guess quality encode from a series of quality
+ * @param quality a series of quality in ascii
+ * @return
+ */
+QualityEncode guess_quality_encode(const std::string& quality);
+
+QualityEncode guess_quality_encode(FastqIO& stream, size_t num_to_guess);
+
+/**
+ * get the possible range of decoded quality of a specific quality encoding
+ * @param encode
+ * @param qual_from output for minimum possible value of encode
+ * @param qual_to output for maximum possible value of encode
+ */
+void get_quality_range(QualityEncode encode, int16_t& qual_from, int16_t& qual_to);
+
+/**
+ * get the ascii offset of a specific quality encoding
+ * @param encode
+ * @return The offset. Currently there are only 33-based and 64-based. -1 for invalid encode.
+ */
+inline int16_t get_quality_offset(QualityEncode encode)
+{
+ switch (encode)
+ {
+ case ENCODE_SANGER:
+ case ENCODE_CASAVA_1_8:
+ return 33;
+ case ENCODE_SOLEXA:
+ case ENCODE_ILLUMINA:
+ return 64;
+ default:
+ return -1;
+ }
+}
+
+inline float quality_to_probability(int16_t qual, QualityEncode encode)
+{
+ float tmp = pow(10.0, float(qual) / -10.0);
+
+ switch (encode)
+ {
+ case ENCODE_SANGER:
+ case ENCODE_CASAVA_1_8:
+ return tmp;
+ case ENCODE_SOLEXA:
+ case ENCODE_ILLUMINA:
+ return tmp / (1.0 + tmp);
+ default:
+ return -1;
+ }
+}
+
+inline int16_t probability_to_quality(float p, QualityEncode encode)
+{
+ int16_t q = 0;
+ switch (encode)
+ {
+ case ENCODE_SANGER:
+ case ENCODE_CASAVA_1_8:
+ q = round(-10 * log10(p));
+ break;
+ case ENCODE_SOLEXA:
+ case ENCODE_ILLUMINA:
+ q = round(-10 * log10(p / (1.0 - p)));
+ break;
+ default:
+ q = -1;
+ break;
+ }
+
+ if (encode == ENCODE_CASAVA_1_8)
+ {
+ if (q < 2) q = 2;
+ else if (q > 41) q = 41;
+ }
+
+ return q;
+}
+
+/**
+ * decode ascii quality
+ * @param data quality in ascii
+ * @param encode
+ * @return decoded quality
+ */
+inline int16_t decode_quality(char data, QualityEncode encode)
+{
+ return data - get_quality_offset(encode);
+}
+
+/**
+ * decode a series of ascii quality
+ * @param input a series of quality in ascii
+ * @param output a series of decoded quality
+ * @param encode
+ */
+void decode_quality(const std::string& input, std::vector<int16_t>& output, QualityEncode encode);
+
+/**
+ * encode a series of quality to ascii
+ * @param input a series of quality
+ * @param output a series of quality in ascii
+ * @param encode
+ */
+void encode_quality(const std::vector<int16_t>& input, std::string& output, QualityEncode encode);
+
+/**
+ *
+ * @param input
+ * @param output
+ * @param encode_input
+ * @param encode_output
+ */
+void recode_quality(const std::string& input, std::string& output, QualityEncode encode_input, QualityEncode encode_output);
+
+} // namespace htio2
+
+#endif /* HTIO2_QUALITY_UTIL_H */
+
diff --git a/src/htio2/RefCounted.cpp b/src/htio2/RefCounted.cpp
new file mode 100644
index 0000000..1b46877
--- /dev/null
+++ b/src/htio2/RefCounted.cpp
@@ -0,0 +1,12 @@
+#include "htio2/RefCounted.h"
+
+namespace htio2
+{
+
+RefCounted::RefCounted(): counter() { }
+
+RefCounted::RefCounted(const RefCounted &other): counter() { }
+
+RefCounted::~RefCounted() { }
+
+} // namespace htio2
diff --git a/src/htio2/RefCounted.h b/src/htio2/RefCounted.h
new file mode 100644
index 0000000..1b69ddf
--- /dev/null
+++ b/src/htio2/RefCounted.h
@@ -0,0 +1,156 @@
+#ifndef HTIO2_REF_COUNTED_H
+#define HTIO2_REF_COUNTED_H
+
+#include <stdint.h>
+#include "JUCE-3.0.8/JuceHeader.h"
+
+class TestFramework;
+
+namespace htio2
+{
+
+class RefCounted
+{
+ friend class ::TestFramework;
+public:
+ RefCounted();
+ RefCounted(const RefCounted& other);
+ virtual ~RefCounted();
+
+ RefCounted& operator=(const RefCounted& other);
+
+ inline void ref() const;
+ inline void unref() const;
+ inline uint32_t get_ref_count() const;
+
+private:
+ mutable juce::Atomic<uint32_t> counter;
+};
+
+inline RefCounted& RefCounted::operator=(const RefCounted& other)
+{
+ return *this;
+}
+
+inline void RefCounted::ref() const
+{
+ ++counter;
+}
+
+inline void RefCounted::unref() const
+{
+ if (--counter == 0)
+ delete this;
+}
+
+inline uint32_t RefCounted::get_ref_count() const
+{ return counter.get(); }
+
+inline void intrusive_ptr_add_ref(RefCounted* self)
+{ self->ref(); }
+
+inline void intrusive_ptr_release(RefCounted* self)
+{ self->unref(); }
+
+inline void smart_ref(const RefCounted* obj)
+{ obj->ref(); }
+
+inline void smart_unref(const RefCounted* obj)
+{ obj->unref(); }
+
+template <typename T>
+class SmartPtr
+{
+ friend class RefCounted;
+ friend class __tester__;
+ template<typename T1, typename T2>
+ friend bool operator == (const SmartPtr<T1>& a, const SmartPtr<T2>& b);
+ template<typename T1, typename T2>
+ friend bool operator < (const SmartPtr<T1>& a, const SmartPtr<T2>& b);
+public:
+ SmartPtr(): m_obj(0) {}
+
+ SmartPtr(T* obj): m_obj(obj)
+ {
+ if (m_obj)
+ smart_ref(m_obj);
+ }
+
+ SmartPtr(const SmartPtr& other): m_obj(other.m_obj)
+ {
+ if (m_obj)
+ smart_ref(m_obj);
+ }
+
+ ~SmartPtr()
+ {
+ if (m_obj)
+ smart_unref(m_obj);
+ }
+
+ SmartPtr& operator = (const SmartPtr& other)
+ {
+ if (m_obj)
+ smart_unref(m_obj);
+
+ m_obj = other.m_obj;
+
+ if (m_obj)
+ smart_ref(m_obj);
+
+ return *this;
+ }
+
+ SmartPtr& operator = (T* other)
+ {
+ if (m_obj)
+ smart_unref(m_obj);
+
+ m_obj = other;
+
+ if (m_obj)
+ smart_ref(m_obj);
+
+ return *this;
+ }
+
+ operator bool() const
+ {
+ return m_obj;
+ }
+
+ T* get() const
+ {
+ return m_obj;
+ }
+
+ T& operator*() const
+ {
+ return *m_obj;
+ }
+
+ T* operator->() const
+ {
+ return m_obj;
+ }
+
+protected:
+ T* m_obj;
+};
+
+template<typename T1, typename T2>
+bool operator == (const SmartPtr<T1>& a, const SmartPtr<T2>& b)
+{
+ return a.m_obj == b.m_obj;
+}
+
+template<typename T1, typename T2>
+bool operator < (const SmartPtr<T1>& a, const SmartPtr<T2>& b)
+{
+ return a.m_obj < b.m_obj;
+}
+
+} // namespace htio2
+
+#endif /* HTIO2_REF_COUNTED_H */
+
diff --git a/src/htio2/RingBuffer.h b/src/htio2/RingBuffer.h
new file mode 100644
index 0000000..7445ff4
--- /dev/null
+++ b/src/htio2/RingBuffer.h
@@ -0,0 +1,95 @@
+#ifndef HTIO2_RING_BUFFER_H
+#define HTIO2_RING_BUFFER_H
+
+#include <stdint.h>
+#include <limits>
+#include "JUCE-3.0.8/JuceHeader.h"
+
+namespace htio2
+{
+
+/**
+ * A single-reader single-writer fixed-size ring buffer
+ */
+template <typename T>
+class RingBuffer
+{
+public:
+ RingBuffer(size_t capacity)
+ : _capacity(capacity)
+ , _size(0)
+ , _i_read_seed(0)
+ , _i_write_seed(0)
+ , _data(new T[capacity])
+ {}
+
+ ~RingBuffer()
+ {
+ delete[] _data;
+ }
+
+ bool push(T value)
+ {
+ if (_size.get() >= _capacity)
+ return false;
+
+ // modify data
+ ssize_t i_write = _i_write_seed;
+ _data[i_write] = value;
+
+ // move write index
+ _i_write_seed = (i_write + 1) % _capacity;
+
+ // update size at last
+ ++_size;
+
+ return true;
+ }
+
+ bool pop(T& result)
+ {
+ if (_size.get() <= 0)
+ return false;
+
+ // read data
+ ssize_t i_read = _i_read_seed;
+ result = _data[i_read];
+
+ // move read index
+ _i_read_seed = (i_read + 1) % _capacity;
+
+ // update size at last
+ --_size;
+
+ return true;
+ }
+
+ void push_sync(T value)
+ {
+ while (!push(value))
+ juce::Thread::yield();
+ }
+
+ void pop_sync(T& result)
+ {
+ while (!pop(result))
+ juce::Thread::yield();
+ }
+
+ ssize_t size()
+ {
+ return _size.value;
+ }
+
+
+protected:
+ T* _data;
+ const size_t _capacity;
+ juce::Atomic<ssize_t> _size;
+ size_t _i_read_seed;
+ size_t _i_write_seed;
+};
+
+} // namespace htio2
+
+#endif // HTIO2_RING_BUFFER_H
diff --git a/src/htio2/SeqIO.cpp b/src/htio2/SeqIO.cpp
new file mode 100644
index 0000000..e9a6033
--- /dev/null
+++ b/src/htio2/SeqIO.cpp
@@ -0,0 +1,99 @@
+#include "htio2/SeqIO.h"
+#include "htio2/Error.h"
+#include "htio2/FormatUtil.h"
+#include "htio2/GzipFileHandle.h"
+#include "htio2/PlainFileHandle.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FastaIO.h"
+#include <zlib.h>
+#include <stdexcept>
+
+using namespace std;
+
+namespace htio2
+{
+
+SeqIO::SeqIO(const std::string& file, IOMode mode, CompressFormat comp)
+{
+ if (comp == COMPRESS_UNKNOWN)
+ comp = guess_compress_by_name(file);
+
+ if (comp == COMPRESS_GZIP)
+ handle = new GzipFileHandle(file.c_str(), mode);
+ else if (comp == COMPRESS_PLAIN)
+ handle = new PlainFileHandle(file.c_str(), mode);
+ else
+ throw InvalidCompressFormat(comp);
+}
+
+SeqIO::SeqIO(FileHandle* handle)
+: handle(handle)
+{
+}
+
+SeqIO::SeqIO(FILE* handle, bool auto_close)
+: handle(new PlainFileHandle(handle, auto_close))
+{
+}
+
+SeqIO::SeqIO(gzFile handle, bool auto_close)
+: handle(new GzipFileHandle(handle, auto_close))
+{
+}
+
+SeqIO* SeqIO::New(const std::string& file, IOMode mode, CompressFormat comp)
+{
+ SeqFormat format = htio2::FORMAT_UNKNOWN;
+ if (mode == htio2::READ)
+ format = guess_format_by_name_and_content(file, comp);
+ else
+ format = guess_format_by_name(file);
+
+ if (format == FORMAT_FASTQ)
+ return new FastqIO(file, mode, comp);
+ else if (format == FORMAT_FASTA)
+ return new FastaIO(file, mode, comp);
+ else
+ throw InvalidSeqFormat(format);
+}
+
+SeqIO* SeqIO::New(FileHandle* handle)
+{
+ SeqFormat format = guess_format_by_content(*handle);
+ switch (format)
+ {
+ case FORMAT_FASTA:
+ return new FastaIO(handle);
+ case FORMAT_FASTQ:
+ return new FastqIO(handle);
+ default:
+ throw InvalidSeqFormat(format);
+ }
+}
+
+SeqIO* SeqIO::New(FILE* handle, bool auto_close)
+{
+ return SeqIO::New(new PlainFileHandle(handle, auto_close));
+}
+
+SeqIO* SeqIO::New(gzFile handle, bool auto_close)
+{
+ return SeqIO::New(new GzipFileHandle(handle, auto_close));
+}
+
+SeqIO::~SeqIO()
+{
+ delete handle;
+}
+
+void SeqIO::seek(off_t offset, int whence)
+{
+ handle->seek(offset, whence);
+}
+
+off_t SeqIO::tell() const
+{
+ return handle->tell();
+}
+
+} // namespace htio2
diff --git a/src/htio2/SeqIO.h b/src/htio2/SeqIO.h
new file mode 100644
index 0000000..dccd50a
--- /dev/null
+++ b/src/htio2/SeqIO.h
@@ -0,0 +1,139 @@
+#ifndef HTIO2_SEQ_IO_H
+#define HTIO2_SEQ_IO_H
+
+#include <zlib.h>
+
+#include "htio2/Enum.h"
+#include "htio2/RefCounted.h"
+
+
+namespace htio2
+{
+
+class SimpleSeq;
+class FastqSeq;
+class FileHandle;
+
+
+class SeqIO : public RefCounted
+{
+public:
+ typedef SmartPtr<SeqIO> Ptr;
+ typedef SmartPtr<const SeqIO> ConstPtr;
+
+public:
+ /**
+ * create sequence IO object by file name
+ * @param file file to open
+ * @param mode read/write/append
+ * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
+ */
+ SeqIO(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);
+
+ /**
+ * create sequence IO object from HTIO file handle object
+ * @param handle
+ */
+ SeqIO(FileHandle* handle);
+
+ /**
+ * create sequence IO object from C standard file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
+ */
+ SeqIO(FILE* handle, bool auto_close = true);
+
+ /**
+ * create sequence IO object from Zlib file handle
+ * @param handle
+ * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
+ */
+ SeqIO(gzFile handle, bool auto_close = true);
+
+ /**
+ * Create a sequence IO object. The sequence format is automatically guessed by file name and/or content.
+ * @param file filename
+ * @param mode READ/WRITE/APPEND
+ * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
+ * @return the newly created sequence IO object
+ */
+ static SeqIO* New(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);
+
+ /**
+ * Create a sequence IO object from HTIO FileHandle object. The sequence format is automatically guessed by file content.
+ * @param handle HTIO FileHandle object. Must be readable.
+ * @return the newly created sequence IO object
+ */
+ static SeqIO* New(FileHandle* handle);
+
+ /**
+ * Create a sequence IO object from C standard file handle. The sequence format is automatically guessed by file content.
+ * @param handle C standard file handle. Must be readable.
+ * @param auto_close If set to true, the underlying handle will be closed when the sequence IO object is destroyed.
+ * @return
+ */
+ static SeqIO* New(FILE* handle, bool auto_close = true);
+
+ /**
+ * Create a sequence IO object from Zlib file handle. The sequence format is automatically guessed by file content.
+ * @param handle Zlib file handle
+ * @param auto_close If set to true, the underlying handle will be closed when the sequence IO object is destroyed.
+ * @return
+ */
+ static SeqIO* New(gzFile handle, bool auto_close = true);
+
+ virtual ~SeqIO();
+
+ /**
+ * Seek to a file offset.
+ * @param offset
+ * @param whence 0 for absolute, 1 for relative
+ */
+ virtual void seek(off_t offset, int whence = SEEK_SET);
+
+ /**
+ * get the current file offset
+ * @return file offset.
+ */
+ virtual off_t tell() const;
+
+
+ /**
+ * read one sequence
+ * @param result
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(SimpleSeq& output) = 0;
+
+ /**
+ * read one sequence with quality
+ * @param result
+ * @return true if got a seq, false if reached end of file
+ */
+ virtual bool next_seq(FastqSeq& output) = 0;
+
+ /**
+ * write one sequence
+ * @param seq the sequence to be written
+ */
+ virtual void write_seq(const SimpleSeq& seq) = 0;
+
+ /**
+ * write one sequence
+ * @param seq the sequence to be written
+ */
+ virtual void write_seq(const FastqSeq& seq) = 0;
+
+protected:
+ FileHandle* handle;
+ std::string buffer;
+
+private:
+ SeqIO(const SeqIO& other);
+ SeqIO& operator =(const SeqIO& other);
+};
+
+} // namespace htio2
+
+#endif /* HTIO2_SEQ_IO_H */
+
diff --git a/src/htio2/SimpleSeq.cpp b/src/htio2/SimpleSeq.cpp
new file mode 100644
index 0000000..320a191
--- /dev/null
+++ b/src/htio2/SimpleSeq.cpp
@@ -0,0 +1,89 @@
+/*
+ * File: FastaSeq.cpp
+ * Author: yangxi
+ *
+ * Created on December 25, 2012, 3:15 PM
+ */
+
+#include "htio2/SimpleSeq.h"
+#include "Error.h"
+
+namespace htio2
+{
+
+void revcom(const std::string& in, std::string& out)
+{
+ out.clear();
+ out.reserve(in.size());
+ for (int i = in.size() - 1; i >= 0; i--)
+ {
+ char comp = 0;
+ switch (in[i])
+ {
+ case 'A':
+ comp = 'T';
+ break;
+ case 'a':
+ comp = 't';
+ break;
+ case 'T':
+ comp = 'A';
+ break;
+ case 't':
+ comp = 'a';
+ break;
+ case 'G':
+ comp = 'C';
+ break;
+ case 'g':
+ comp = 'c';
+ break;
+ case 'C':
+ comp = 'G';
+ break;
+ case 'c':
+ comp = 'g';
+ break;
+ case 'N':
+ comp = 'N';
+ break;
+ case 'n':
+ comp = 'n';
+ break;
+ }
+ if (!comp)
+ throw InvalidRevcom(in);
+ out.push_back(comp);
+ }
+}
+
+SimpleSeq::SimpleSeq()
+{
+}
+
+SimpleSeq::SimpleSeq(const std::string& id, const std::string& desc, const std::string& seq) :
+id(id),
+desc(desc),
+seq(seq)
+{
+}
+
+SimpleSeq::~SimpleSeq()
+{
+}
+
+void SimpleSeq::revcom(SimpleSeq& result) const
+{
+ result.id = id;
+ result.desc = desc;
+ htio2::revcom(seq, result.seq);
+}
+
+void SimpleSeq::subseq(SimpleSeq& result, size_t start, size_t length) const
+{
+ result.id = id;
+ result.desc = desc;
+ result.seq.assign(seq, start, length);
+}
+
+} // namespace htio2
diff --git a/src/htio2/SimpleSeq.h b/src/htio2/SimpleSeq.h
new file mode 100644
index 0000000..f726fc1
--- /dev/null
+++ b/src/htio2/SimpleSeq.h
@@ -0,0 +1,87 @@
+#ifndef HTIO2_SIMPLE_SEQ_H
+#define HTIO2_SIMPLE_SEQ_H
+
+#include <string>
+
+#include "htio2/RefCounted.h"
+
+namespace htio2
+{
+
+/**
+ * generate reverse complement nucleotide sequence
+ * @param in input sequence
+ * @param out output result
+ */
+void revcom(const std::string& in, std::string& out);
+
+/**
+ * @brief a simple sequence class with ID, description and sequence content
+ */
+class SimpleSeq : public RefCounted
+{
+public:
+ typedef SmartPtr<SimpleSeq> Ptr;
+ typedef SmartPtr<const SimpleSeq> ConstPtr;
+
+public:
+ /**
+ * Create an empty sequence object
+ */
+ SimpleSeq();
+
+ /**
+ * create an sequence object with ID, description and sequence
+ * @param id
+ * @param desc
+ * @param seq
+ */
+ SimpleSeq(const std::string& id, const std::string& desc, const std::string& seq);
+ virtual ~SimpleSeq();
+
+ /**
+ * get sequence length
+ * @return sequence length
+ */
+ inline size_t length() const
+ {
+ return seq.length();
+ }
+ /**
+ * generate reverse complement sequence
+ * @param result
+ */
+ void revcom(SimpleSeq& result) const;
+
+ /**
+ * @brief subseq
+ * @param result
+ * @param start
+ * @param length
+ */
+ void subseq(std::string& result, size_t start, size_t length = std::string::npos) const;
+
+ /**
+ * get part of the sequence
+ * @param result
+ * @param start the start of sub sequence, 0 for the first base
+ * @param length the length of sub sequence
+ */
+ void subseq(SimpleSeq& result, size_t start, size_t length = std::string::npos) const;
+
+ std::string id;
+ std::string desc;
+ std::string seq;
+private:
+
+};
+
+inline void SimpleSeq::subseq(std::string& result, size_t start, size_t length) const
+{
+ result.assign(seq, start, length);
+}
+
+} // namespace htio2
+
+#endif /* HTIO2_SIMPLE_SEQ_H */
+
diff --git a/src/htio2/StringUtil.cpp b/src/htio2/StringUtil.cpp
new file mode 100644
index 0000000..e5a0e96
--- /dev/null
+++ b/src/htio2/StringUtil.cpp
@@ -0,0 +1,34 @@
+#include "htio2/StringUtil.h"
+
+using namespace std;
+
+namespace htio2
+{
+
+string to_upper_case(const std::string& input)
+{
+ string result(input.size(), '\0');
+ for (size_t i = 0; i < input.size(); i++)
+ {
+ char chr = input[i];
+ if ('a' <= chr && chr <= 'z')
+ chr -= 'a' - 'A';
+ result[i] = chr;
+ }
+ return result;
+}
+
+string to_lower_case(const std::string& input)
+{
+ string result(input.size(), '\0');
+ for (size_t i = 0; i < input.size(); i++)
+ {
+ char chr = input[i];
+ if ('A' <= chr && chr <= 'Z')
+ chr += 'a' - 'A';
+ result[i] = chr;
+ }
+ return result;
+}
+
+} // namespace htio2
diff --git a/src/htio2/StringUtil.h b/src/htio2/StringUtil.h
new file mode 100644
index 0000000..713f6cf
--- /dev/null
+++ b/src/htio2/StringUtil.h
@@ -0,0 +1,55 @@
+#ifndef HTIO2_STRING_UTIL_H
+#define HTIO2_STRING_UTIL_H
+
+#include <string>
+#include <vector>
+
+namespace htio2
+{
+
+#define STRINGIFY(content) #content
+#define EXPAND_AND_STRINGIFY(input) STRINGIFY(input)
+
+std::string to_upper_case(const std::string& input);
+std::string to_lower_case(const std::string& input);
+
+template <typename iterator_t>
+std::string join(const std::string& delim, iterator_t input_begin, iterator_t input_end)
+{
+ std::string result;
+ for (iterator_t it = input_begin; it != input_end; it++)
+ {
+ if (it != input_begin)
+ result += delim;
+ result += *it;
+ }
+ return result;
+}
+
+template <typename container_t>
+void split(const std::string& input, char delim, container_t& output)
+{
+ if (!input.length())
+ return;
+
+ size_t search_from = 0;
+ for (;;)
+ {
+ size_t i_delim = input.find(delim, search_from);
+
+ if (i_delim == std::string::npos)
+ {
+ output.push_back(input.substr(search_from));
+ break;
+ }
+ else
+ {
+ output.push_back(input.substr(search_from, i_delim - search_from));
+ search_from = i_delim + 1;
+ }
+ }
+}
+
+} // namespace htio2
+
+#endif // HTIO2_STRING_UTIL_H
diff --git a/src/htio2/Version.cpp b/src/htio2/Version.cpp
new file mode 100644
index 0000000..fa443f0
--- /dev/null
+++ b/src/htio2/Version.cpp
@@ -0,0 +1,18 @@
+#include "htio2/Version.h"
+#include "htio2/config.h"
+
+#include <sstream>
+
+using namespace std;
+
+namespace htio2
+{
+
+std::string get_version_string()
+{
+ ostringstream result;
+ result << HTIO_VERSION_MAJOR << "." << HTIO_VERSION_MINOR << "." << HTIO_VERSION_PATCH;
+ return result.str();
+}
+
+} // namespace htio2
diff --git a/src/htio2/Version.h b/src/htio2/Version.h
new file mode 100644
index 0000000..d31b1a8
--- /dev/null
+++ b/src/htio2/Version.h
@@ -0,0 +1,18 @@
+#ifndef HTIO2_VERSION_H
+#define HTIO2_VERSION_H
+
+#include <string>
+
+namespace htio2
+{
+
+/**
+ * get the version of HTIO library
+ * @return version string formatted in "MAJOR.MINOR.PATCH"
+ */
+std::string get_version_string();
+
+} // namespace htio2
+
+#endif /* HTIO2_VERSION_H */
+
diff --git a/src/htio2/config.h.in b/src/htio2/config.h.in
new file mode 100644
index 0000000..d3f0583
--- /dev/null
+++ b/src/htio2/config.h.in
@@ -0,0 +1,8 @@
+#ifndef HTIO_CONFIG_H
+#define HTIO_CONFIG_H
+
+#define HTIO_VERSION_MAJOR @CPACK_PACKAGE_VERSION_MAJOR@
+#define HTIO_VERSION_MINOR @CPACK_PACKAGE_VERSION_MINOR@
+#define HTIO_VERSION_PATCH @CPACK_PACKAGE_VERSION_PATCH@
+
+#endif
diff --git a/src/htqc/App.cpp b/src/htqc/App.cpp
new file mode 100644
index 0000000..cde576b
--- /dev/null
+++ b/src/htqc/App.cpp
@@ -0,0 +1,41 @@
+#include "htqc/App.h"
+#include "htio2/Cast.h"
+
+using namespace htqc;
+using namespace std;
+
+int main(int argc, char** argv)
+{
+ // parse and validate options
+ parse_options(argc, argv);
+ validate_options();
+
+ // guess compression by input files
+ OPT_compress = guess_compress_format_by_files_name(OPT_files_in);
+ if (OPT_compress == htio2::COMPRESS_UNKNOWN)
+ {
+ cerr << "ERROR: failed to guess compress format from input files" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // show options
+ if (!OPT_quiet)
+ {
+ std::cout << std::endl
+ << "#---------------------------------#" << std::endl
+ << "#" << std::endl
+ << "# Options:" << std::endl
+ << "#" << std::endl;
+ show_options();
+ std::cout << "# compress: " << htio2::to_string(OPT_compress) << std::endl
+ << "#" << std::endl
+ << "#---------------------------------#" << std::endl
+ << std::endl;
+ }
+
+ // run
+ if (!OPT_quiet) std::cout << "start processing" << std::endl;
+ execute();
+ if (!OPT_quiet) std::cout << "done" << std::endl;
+}
+
diff --git a/src/htqc/App.h b/src/htqc/App.h
new file mode 100644
index 0000000..2ab1305
--- /dev/null
+++ b/src/htqc/App.h
@@ -0,0 +1,14 @@
+#ifndef HTQC_APP_H
+#define HTQC_APP_H
+
+#include <iostream>
+
+#include "htqc/Options.h"
+
+void parse_options(int argc, char** argv);
+void validate_options();
+void show_options();
+void execute();
+
+#endif /* HTQC_APP_H */
+
diff --git a/src/htqc/BaseQualCounter.cpp b/src/htqc/BaseQualCounter.cpp
new file mode 100644
index 0000000..9190d6a
--- /dev/null
+++ b/src/htqc/BaseQualCounter.cpp
@@ -0,0 +1,112 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "htqc/BaseQualCounter.h"
+#include "htio2/QualityUtil.h"
+
+using namespace htqc;
+using namespace std;
+
+BaseCounter& BaseCounter::operator+=(const htqc::BaseCounter& other)
+{
+ a += other.a;
+ t += other.t;
+ g += other.g;
+ c += other.c;
+ n += other.n;
+ mask += other.mask;
+ return *this;
+}
+
+TileQualCounter& TileQualCounter::operator+=(const htqc::TileQualCounter& other)
+{
+ num_reads_10 += other.num_reads_10;
+ num_reads_10_20 += other.num_reads_10_20;
+ num_reads_20_30 += other.num_reads_20_30;
+ num_reads_30 += other.num_reads_30;
+ return *this;
+}
+
+BaseQualCounter::BaseQualCounter(htio2::QualityEncode encode)
+: key_max(-1)
+, from(-1)
+, to(-1)
+{
+ htio2::get_quality_range(encode, from, to);
+ key_max = to - from;
+ counter.resize(key_max + 1, 0);
+}
+
+void BaseQualCounter::create_chart(BaseQualBoxChart& chart) const
+{
+ long num_seq = 0;
+ for (int qual = from; qual <= to; qual++)
+ {
+ num_seq += get_num(qual);
+ }
+
+ long i_dec_low = num_seq / 10;
+ long i_quat_low = num_seq / 4;
+ long i_median = num_seq / 2;
+ long i_quat_high = num_seq * 3 / 4;
+ long i_dec_high = num_seq * 9 / 10;
+
+ long seq_sum = 0;
+ long qual_sum = 0;
+ for (int qual = from; qual <= to; qual++)
+ {
+ long num = get_num(qual);
+ long seq_sum_next = seq_sum + num;
+ qual_sum += qual*num;
+
+ if (seq_sum < i_dec_low && i_dec_low <= seq_sum_next)
+ {
+ chart.dec_low = qual;
+ }
+ if (seq_sum < i_quat_low && i_quat_low <= seq_sum_next)
+ {
+ chart.quat_low = qual;
+ }
+ if (seq_sum < i_median && i_median <= seq_sum_next)
+ {
+ chart.median = qual;
+ }
+ if (seq_sum < i_quat_high && i_quat_high <= seq_sum_next)
+ {
+ chart.quat_high = qual;
+ }
+ if (seq_sum < i_dec_high && i_dec_high <= seq_sum_next)
+ {
+ chart.dec_high = qual;
+ }
+
+ seq_sum = seq_sum_next;
+ }
+
+ if (num_seq == 0)
+ chart.mean = 0;
+ else
+ chart.mean = double(qual_sum) / double(num_seq);
+}
+
+BaseQualCounter& BaseQualCounter::operator+=(const htqc::BaseQualCounter& other)
+{
+ for (int i = 0; i < other.counter.size(); i++)
+ {
+ counter[i] += other.counter[i];
+ }
+ return *this;
+}
diff --git a/src/htqc/BaseQualCounter.h b/src/htqc/BaseQualCounter.h
new file mode 100644
index 0000000..1e3b532
--- /dev/null
+++ b/src/htqc/BaseQualCounter.h
@@ -0,0 +1,112 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef HTQC_BASEQUALCOUNTER_H
+#define HTQC_BASEQUALCOUNTER_H
+
+#include "htqc/Common.h"
+
+namespace htqc
+{
+
+class BaseCounter
+{
+public:
+
+ BaseCounter(): a(0), t(0), g(0), c(0), n(0), mask(0) { }
+ long a;
+ long t;
+ long g;
+ long c;
+ long n;
+ long mask;
+
+ BaseCounter& operator+=(const BaseCounter& other);
+};
+
+class TileQualCounter
+{
+public:
+
+ TileQualCounter()
+ : num_reads_10(0)
+ , num_reads_10_20(0)
+ , num_reads_20_30(0)
+ , num_reads_30(0) { }
+
+ inline void record(int qual)
+ {
+ if (qual < 10) num_reads_10++;
+ else if (qual < 20) num_reads_10_20++;
+ else if (qual < 30) num_reads_20_30++;
+ else num_reads_30++;
+ }
+ long num_reads_10;
+ long num_reads_10_20;
+ long num_reads_20_30;
+ long num_reads_30;
+ TileQualCounter& operator+=(const TileQualCounter& other);
+};
+
+typedef struct
+{
+ int dec_low;
+ int quat_low;
+ int median;
+ int quat_high;
+ int dec_high;
+ float mean;
+} BaseQualBoxChart;
+
+class BaseQualCounter
+{
+public:
+
+ BaseQualCounter(htio2::QualityEncode encode);
+
+ inline void record(int qual)
+ {
+ int key = qual - from;
+ if (key > key_max || key < 0)
+ {
+ char err_msg[2048];
+ std::sprintf(err_msg, "invalid quality: %d (key %d), valid range %d - %d", qual, key, from, to);
+ throw std::runtime_error(std::string(err_msg));
+ }
+ counter[key]++;
+ }
+
+ inline long get_num(int qual) const
+ {
+ int key = qual - from;
+ return counter[key];
+ }
+
+ void create_chart(BaseQualBoxChart& chart) const;
+
+ BaseQualCounter& operator+=(const BaseQualCounter& other);
+
+protected:
+ std::vector<long> counter;
+
+ int key_max;
+ int16_t from;
+ int16_t to;
+};
+
+}
+
+#endif // HTQC_BASEQUALCOUNTER_H
diff --git a/src/htqc/Common.cpp b/src/htqc/Common.cpp
new file mode 100644
index 0000000..21e1ae9
--- /dev/null
+++ b/src/htqc/Common.cpp
@@ -0,0 +1,96 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#include "htqc/Common.h"
+#include "htio2/JUCE-3.0.8/JuceHeader.h"
+
+using namespace std;
+using namespace htio2;
+
+namespace htqc
+{
+const int LOG_BLOCK = 50000;
+const size_t NUM_GUESS = 500;
+
+std::string bool_to_string(bool value)
+{
+ return value ? "T" : "F";
+}
+
+void check_output_overwrite(const std::vector<std::string>& files_in,
+ const std::string& file_out)
+{
+ for (size_t i = 0; i < files_in.size(); i++)
+ {
+ if (juce::File(files_in[i]) == juce::File(file_out))
+ {
+ cerr << "output file \"" << file_out << "\" will overwrite input file \"" << files_in[i] << "\"" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void separate_paired_files(const std::vector<std::string>& in, std::vector<std::string>& names_a, std::vector<std::string>& names_b)
+{
+ size_t size = in.size();
+
+ if (size % 2)
+ {
+ cerr << "ERROR: odd number of files for paired-end mode: " << size << endl;
+ for (int i = 0; i < size; i++)
+ {
+ cerr << " " << in[i] << endl;
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ int half = size / 2;
+
+ for (int i = 0; i < half; i++)
+ names_a.push_back(in[i]);
+
+ for (int i = half; i < size; i++)
+ names_b.push_back(in[i]);
+}
+
+void add_fastq_suffix_se(const std::string& prefix,
+ htio2::CompressFormat comp,
+ std::string& file)
+{
+ file = prefix + ".fastq";
+ if (comp == htio2::COMPRESS_GZIP)
+ file += ".gz";
+}
+
+void add_fastq_suffix_pe(const std::string& prefix,
+ htio2::CompressFormat comp,
+ std::string& file1,
+ std::string& file2)
+{
+ file1 = prefix + "_1.fastq";
+ file2 = prefix + "_2.fastq";
+ if (comp == htio2::COMPRESS_GZIP)
+ {
+ file1 += ".gz";
+ file2 += ".gz";
+ }
+}
+
+} // namespace htqc
+
+
+
+
+
+
diff --git a/src/htqc/Common.h b/src/htqc/Common.h
new file mode 100644
index 0000000..1ec41f8
--- /dev/null
+++ b/src/htqc/Common.h
@@ -0,0 +1,63 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#ifndef HTQC_COMMON_H
+#define HTQC_COMMON_H
+
+#include "ht_config.h"
+#include "htio2/Enum.h"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <stdexcept>
+#include <vector>
+#include <map>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <stdint.h>
+
+#define CACHE_LINE_ALIGNMENT __attribute__ ((aligned (32)))
+
+namespace htqc
+{
+
+extern const int LOG_BLOCK;
+extern const size_t NUM_GUESS;
+
+std::string bool_to_string(bool value);
+
+void check_output_overwrite(const std::vector<std::string>& files_in,
+ const std::string& file_out);
+
+void separate_paired_files(const std::vector<std::string>& in,
+ std::vector<std::string>& names_a,
+ std::vector<std::string>& names_b);
+
+void add_fastq_suffix_se(const std::string& prefix,
+ htio2::CompressFormat comp,
+ std::string& file);
+
+void add_fastq_suffix_pe(const std::string& prefix,
+ htio2::CompressFormat comp,
+ std::string& file1,
+ std::string& file2);
+
+}
+
+
+#endif
diff --git a/src/htqc/FastqStat.cpp b/src/htqc/FastqStat.cpp
new file mode 100644
index 0000000..cbc91d8
--- /dev/null
+++ b/src/htqc/FastqStat.cpp
@@ -0,0 +1,184 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <vector>
+
+#include "htqc/FastqStat.h"
+#include "htio2/QualityUtil.h"
+
+using namespace htio2;
+using namespace std;
+
+namespace htqc
+{
+
+FastqStat::FastqStat(bool mask, QualityEncode encode, HeaderFormat h_format, bool h_sra) :
+header_parser(h_format, h_sra),
+encode(encode),
+observed_max_len(0),
+qual_mask(mask),
+read_quals(),
+read_qual_counter(encode)
+{
+ get_quality_range(encode, qual_from, qual_to);
+}
+
+FastqStat::~FastqStat()
+{
+}
+
+void FastqStat::record_seq(FastqSeq& seq)
+{
+ // validate length
+ int len = seq.length();
+ if (len > observed_max_len)
+ try_expand_store(len);
+
+ //
+ // parse lane and tile
+ //
+ header_parser.parse(seq.id, seq.desc);
+
+ //
+ //
+ // traverse through bases
+ int valid_len = 0;
+ float qual_sum = 0;
+
+ for (int i = 0; i < len; i++)
+ {
+ // get quality
+ int qual = decode_quality(seq.quality[i], encode);
+ if (qual == 0)
+ {
+ printf("");
+ }
+
+ //base_qual_counter[i].record(qual);
+ base_qual_counter.at(i).record(qual);
+
+ // check mask
+ if (qual_mask)
+ {
+ if (qual < 2)
+ {
+ cerr << "for quality score with mask, values below 2 are not used, but we got " << qual << " in " << seq.id << endl;
+ throw runtime_error("invalid base quality");
+ }
+ else if (qual == 2)
+ {
+ base_compo_counter[i].mask++;
+ continue;
+ }
+ }
+
+ // add base quality to read quality
+ valid_len++;
+ qual_sum += qual;
+
+ // record base composition
+ switch (seq.seq[i])
+ {
+ case 'A':
+ case 'a':
+ base_compo_counter[i].a++;
+ break;
+ case 'T':
+ case 't':
+ base_compo_counter[i].t++;
+ break;
+ case 'G':
+ case 'g':
+ base_compo_counter[i].g++;
+ break;
+ case 'C':
+ case 'c':
+ base_compo_counter[i].c++;
+ break;
+ case 'N':
+ case 'n':
+ base_compo_counter[i].n++;
+ break;
+ }
+ }
+
+ // record length
+ read_len_counter.at(valid_len)++;
+
+ // calculate and record read quality
+ float read_qual = qual_sum / len;
+ read_quals.push_back(read_qual);
+ read_qual_counter.record(int(read_qual));
+ tile_read_qual_counter[header_parser.lane][header_parser.tile].record(int(read_qual));
+}
+
+FastqStat& FastqStat::operator+=(const htqc::FastqStat& other)
+{
+ if (observed_max_len < other.observed_max_len) try_expand_store(other.observed_max_len);
+ if (encode != other.encode) throw runtime_error("encode not same");
+ if (qual_mask != other.qual_mask) throw runtime_error("qual_mask not same");
+
+ read_quals.reserve(read_quals.size() + other.read_quals.size());
+ for (std::vector<float>::const_iterator it = other.read_quals.begin(); it != other.read_quals.end(); it++)
+ {
+ read_quals.push_back(*it);
+ }
+
+ for (int i = 0; i < observed_max_len; i++)
+ {
+ base_qual_counter[i] += other.base_qual_counter[i];
+ base_compo_counter[i] += other.base_compo_counter[i];
+ }
+
+ read_qual_counter += other.read_qual_counter;
+
+ for (int i = 0; i <= observed_max_len; i++)
+ read_len_counter[i] += other.read_len_counter[i];
+
+ for (
+ map< int, map<int, TileQualCounter> >::const_iterator it_lane = other.tile_read_qual_counter.begin();
+ it_lane != other.tile_read_qual_counter.end();
+ it_lane++
+ )
+ {
+ int lane = it_lane->first;
+ const map<int, TileQualCounter>* lane_quals = &(it_lane->second);
+
+ for (
+ map<int, TileQualCounter>::const_iterator it_tile = lane_quals->begin();
+ it_tile != lane_quals->end();
+ it_tile++
+ )
+ {
+ int tile = it_tile->first;
+ tile_read_qual_counter[lane][tile] += it_tile->second;
+ }
+ }
+
+ return *this;
+}
+
+void FastqStat::try_expand_store(size_t new_size)
+{
+ if (new_size > observed_max_len)
+ {
+ observed_max_len = new_size;
+ base_qual_counter.resize(new_size, BaseQualCounter(encode));
+ base_compo_counter.resize(new_size);
+ read_len_counter.resize(new_size + 1, 0);
+ }
+}
+
+} // namespace htqc
diff --git a/src/htqc/FastqStat.h b/src/htqc/FastqStat.h
new file mode 100644
index 0000000..b489d8c
--- /dev/null
+++ b/src/htqc/FastqStat.h
@@ -0,0 +1,63 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef HTQC_FASTQSTAT_H
+#define HTQC_FASTQSTAT_H
+
+
+#include <htio2/HeaderUtil.h>
+#include <htio2/FastqSeq.h>
+
+#include "htqc/Common.h"
+#include "htqc/BaseQualCounter.h"
+
+namespace htqc
+{
+
+class FastqStat
+{
+public:
+ FastqStat(bool mask, htio2::QualityEncode encode, htio2::HeaderFormat h_format, bool h_sra);
+
+ ~FastqStat();
+
+ void record_seq(htio2::FastqSeq& seq);
+ FastqStat& operator+=(const FastqStat& other);
+
+ void try_expand_store(size_t new_size);
+
+public:
+ htio2::HeaderParser header_parser;
+
+ htio2::QualityEncode encode;
+ int observed_max_len;
+ int16_t qual_from;
+ int16_t qual_to;
+ bool qual_mask;
+
+ std::vector<float> read_quals;
+ std::vector<BaseQualCounter> base_qual_counter; // cycle => object
+ std::vector<BaseCounter> base_compo_counter; // cycle => object
+ BaseQualCounter read_qual_counter;
+ std::vector<long> read_len_counter; // length => count
+ std::map< int, std::map<int, TileQualCounter> > tile_read_qual_counter; // lane => tile => quality_range => count
+
+
+} CACHE_LINE_ALIGNMENT;
+
+}
+
+#endif // HTQC_FASTQSTAT_H
diff --git a/src/htqc/MicroAssembler.cpp b/src/htqc/MicroAssembler.cpp
new file mode 100644
index 0000000..9128455
--- /dev/null
+++ b/src/htqc/MicroAssembler.cpp
@@ -0,0 +1,289 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "htqc/MicroAssembler.h"
+
+#include "htio2/QualityUtil.h"
+#include "htio2/Kmer.h"
+
+#include <sstream>
+
+#include "stdlib.h"
+
+using namespace std;
+
+namespace htqc
+{
+
+MicroAssembler::MicroAssembler(int kmer_size, int confident_quality, int aln_identity, int conflict_quality_diff)
+: km_sz(kmer_size)
+, conf_qual(confident_quality)
+, aln_iden(aln_identity)
+, qual_diff(conflict_quality_diff)
+{
+}
+
+MicroAssembler::~MicroAssembler()
+{
+}
+
+bool MicroAssembler::assemble(const std::string& seq1,
+ const std::vector<int16_t>& qual_list_1,
+ const std::string& seq2,
+ const std::vector<int16_t>& qual_list_2)
+{
+ result_seq.clear();
+ result_qual.clear();
+ result_desc.clear();
+
+ size_t len_a = seq1.length();
+ size_t len_b = seq2.length();
+
+ // generate quality mask
+ vector<bool> qual_mask_a;
+ vector<bool> qual_mask_b;
+ gen_qual_mask(qual_list_1, qual_mask_a);
+ gen_qual_mask(qual_list_2, qual_mask_b);
+
+ // encode sequence
+ // generate kmer profile
+ htio2::EncodedSeq enc_a;
+ htio2::EncodedSeq enc_b;
+ vector<KmerT> kmers_a;
+ vector<KmerT> kmers_b;
+ multimap<KmerT, PosT> kmers_pos_b;
+
+ htio2::encode_nt5(seq1, enc_a);
+ htio2::encode_nt5(seq2, enc_b);
+ htio2::gen_kmer_nt5(enc_a, kmers_a, km_sz);
+ htio2::gen_kmer_nt5(enc_b, kmers_b, km_sz);
+ htio2::summ_kmer_pos(kmers_b, kmers_pos_b);
+
+ //
+ // perform alignment
+ //
+ const ssize_t nk_a = kmers_a.size();
+
+ bool success = false;
+
+ // traverse A position
+ for (PosT i_kmer_a = 0; i_kmer_a < nk_a; i_kmer_a++)
+ {
+ if (!qual_mask_a[i_kmer_a])
+ {
+ continue;
+ }
+
+ const KmerT kmer_a = kmers_a[i_kmer_a];
+ pair<multimap<KmerT,PosT>::const_iterator, multimap<KmerT,PosT>::const_iterator> kb_pos_bound = kmers_pos_b.equal_range(kmer_a);
+
+ // traverse B position
+ for (multimap<KmerT,PosT>::const_iterator it = kb_pos_bound.first; it != kb_pos_bound.second; it++)
+ {
+ const PosT i_kmer_b = it->second;
+ if (!qual_mask_b[i_kmer_b]) continue;
+
+ const size_t len_a_before = i_kmer_a;
+ const size_t len_b_before = i_kmer_b;
+ const size_t len_a_after = len_a - len_a_before;
+ const size_t len_b_after = len_b - len_b_before;
+
+
+ // skip if B lays on left of A
+ if (len_a_before < len_b_before && len_b_after < len_a_after)
+ {
+ continue;
+ }
+
+ // ib = ia + offset
+ const PosT offset = i_kmer_b - i_kmer_a;
+
+ //
+ // check sequence
+ //
+ PosT ia_from = 0;
+ PosT ib_from = 0;
+ if (len_a_before < len_b_before)
+ ib_from = ia_from + offset;
+
+ else
+ ia_from = ib_from - offset;
+
+ PosT ia_to = ia_from;
+ PosT ib_to = ib_from;
+
+ uint16_t iden = 0;
+ bool conflict = false;
+
+ string aligned_part;
+ vector<int16_t> aligned_part_qual;
+
+ while (1)
+ {
+ int16_t qual_a = qual_list_1[ia_to];
+ int16_t qual_b = qual_list_2[ib_to];
+
+ // check base
+ if (enc_a[ia_to] == enc_b[ib_to])
+ {
+ if (qual_a >= conf_qual || qual_b >= conf_qual) iden++;
+ }
+ else
+ {
+ // check quality
+ int curr_qual_diff = abs(qual_a - qual_b);
+ if (curr_qual_diff < qual_diff)
+ {
+ conflict = true;
+ break;
+ }
+ }
+
+ // store base and quality
+ if (qual_a >= qual_b)
+ {
+ aligned_part.push_back(seq1[ia_to]);
+ aligned_part_qual.push_back(qual_list_1[ia_to]);
+ }
+ else
+ {
+ aligned_part.push_back(seq2[ib_to]);
+ aligned_part_qual.push_back(qual_list_2[ib_to]);
+ }
+
+ ia_to++;
+ ib_to++;
+ if (ia_to == len_a || ib_to == len_b) break;
+ }
+
+ // record the assembled sequence
+ if (!conflict && iden >= aln_iden)
+ {
+ success = true;
+
+ ostringstream handle;
+ handle << "kmer_size=" << km_sz
+ << " kmer_pos_a=" << i_kmer_a + 1
+ << " kmer_pos_b=" << i_kmer_b + 1
+ << " num_identical=" << iden;
+ result_desc = handle.str();
+
+ // content before alignment
+ if (ia_from > 0)
+ {
+ result_seq.assign(seq1, 0, ia_from);
+ result_qual.assign(qual_list_1.begin(), qual_list_1.begin() + ia_from);
+ }
+ else if (ib_from > 0)
+ {
+ result_seq.assign(seq2, 0, ib_from);
+ result_qual.assign(qual_list_2.begin(), qual_list_2.begin() + ib_from);
+ }
+
+ // contents that aligned
+ result_seq += aligned_part;
+ result_qual.insert(result_qual.end(), aligned_part_qual.begin(), aligned_part_qual.end());
+
+ // contents after alignment
+ if (ia_to != len_a)
+ {
+ result_seq.append(seq1, ia_to, string::npos);
+ result_qual.insert(result_qual.end(), qual_list_1.begin() + ia_to, qual_list_1.end());
+ }
+ else if (ib_to != len_b)
+ {
+ result_seq.append(seq2, ib_to, string::npos);
+ result_qual.insert(result_qual.end(), qual_list_2.begin() + ib_to, qual_list_2.end());
+ }
+
+ break;
+ }
+ }
+
+ if (success) break;
+ }
+
+ return success;
+}
+
+void MicroAssembler::gen_qual_mask(const vector<int16_t>& quality, std::vector<bool>& mask)
+{
+ // init mask
+ const size_t length = quality.size();
+
+ if (length < km_sz)
+ {
+ mask.resize(0);
+ return;
+ }
+
+ const size_t num_kmer = length - km_sz + 1;
+ mask.resize(num_kmer);
+
+ // check contents
+ size_t i = 0;
+
+ while (i < num_kmer)
+ {
+ // check the first kmer
+ bool ok = true;
+ size_t bad_i = 0;
+
+ for (size_t j = 0; j < km_sz; j++)
+ {
+ size_t i_check = i + j;
+ if (quality[i_check] < conf_qual)
+ {
+ ok = false;
+ bad_i = i_check;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ mask[i] = true;
+ // check next kmer
+ // actually only check one base on the tail
+ i++;
+ for (; i < num_kmer; i++)
+ {
+ size_t i_tail = i + km_sz - 1;
+ if (conf_qual <= quality[i_tail])
+ mask[i] = true;
+ else
+ {
+ // mark false within current kmer range
+ for (; i <= i_tail && i < num_kmer; i++)
+ mask[i] = false;
+ // now i should point to the one after i_tail
+ break;
+ }
+ }
+ }
+ else
+ {
+ // mark bad from i to bad_i
+ for (; i <= bad_i && i < num_kmer; i++)
+ mask[i] = false;
+ // now i should point to the one after bad_i
+ }
+
+ }
+}
+
+
+} // namespace htqc
+
diff --git a/src/htqc/MicroAssembler.h b/src/htqc/MicroAssembler.h
new file mode 100644
index 0000000..9943268
--- /dev/null
+++ b/src/htqc/MicroAssembler.h
@@ -0,0 +1,63 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTQC_MICROASSEMBLER_H
+#define HTQC_MICROASSEMBLER_H
+
+#define USE_encode
+
+#include <string>
+#include <vector>
+
+#include <stdint.h>
+
+namespace htqc
+{
+
+typedef uint64_t KmerT;
+typedef int16_t PosT;
+
+class MicroAssembler
+{
+public:
+ MicroAssembler(int kmer_size, int confident_quality, int aln_identity, int conflict_quality_diff);
+ ~MicroAssembler();
+
+ /// @return true if assembled
+ bool assemble(const std::string& seq1,
+ const std::vector<int16_t>& qual_list_1,
+ const std::string& seq2,
+ const std::vector<int16_t>& qual_list_2);
+
+
+ std::string result_seq;
+ std::vector<int16_t> result_qual;
+ std::string result_desc;
+private:
+ MicroAssembler();
+ MicroAssembler(const MicroAssembler& orig);
+ MicroAssembler& operator=(const MicroAssembler& orig);
+
+ void gen_qual_mask(const std::vector<int16_t>& quality, std::vector<bool>& mask);
+
+ int km_sz;
+ int conf_qual;
+ int aln_iden;
+ int qual_diff;
+};
+
+} // namespace htqc
+#endif /* HTQC_MICROASSEMBLER_H */
+
diff --git a/src/htqc/MultiSeqFile.cpp b/src/htqc/MultiSeqFile.cpp
new file mode 100644
index 0000000..2f4149b
--- /dev/null
+++ b/src/htqc/MultiSeqFile.cpp
@@ -0,0 +1,122 @@
+#include "htqc/MultiSeqFile.h"
+
+#include "htio2/FastqSeq.h"
+#include "htio2/SeqIO.h"
+
+namespace htqc
+{
+
+MultiSeqFileSE::MultiSeqFileSE(const std::vector<std::string>& files,
+ htio2::CompressFormat comp)
+: files(files)
+, fh(htio2::SeqIO::New(files[0], htio2::READ, comp))
+, comp(comp)
+, curr_file_i(0)
+{
+}
+
+MultiSeqFileSE::~MultiSeqFileSE() {}
+
+bool MultiSeqFileSE::next_seq(htio2::FastqSeq& seq)
+{
+ // early out if we have reached the end
+ if (curr_file_i >= files.size())
+ return false;
+
+ while (true)
+ {
+ // try to get next sequence
+ bool re = fh->next_seq(seq);
+ if (re)
+ return true;
+
+ // try the next file
+ fh = nullptr;
+ curr_file_i++;
+ if (curr_file_i >= files.size())
+ return false;
+
+ fh = htio2::SeqIO::New(files[curr_file_i], htio2::READ, comp);
+ }
+}
+
+MultiSeqFilePE::MultiSeqFilePE(const std::vector<std::string>& files,
+ htio2::Strand strand_r1_in_file,
+ htio2::Strand strand_r2_in_file,
+ htio2::CompressFormat comp)
+: files_a(files)
+, fh(new htio2::PairedEndIO(files[0],
+ htio2::READ,
+ strand_r1_in_file,
+ strand_r2_in_file,
+ comp,
+ htio2::FORMAT_UNKNOWN))
+, interleave(true)
+, strand_r1_in_file(strand_r1_in_file)
+, strand_r2_in_file(strand_r2_in_file)
+, comp(comp)
+, curr_file_i(0)
+{
+}
+
+MultiSeqFilePE::MultiSeqFilePE(const std::vector<std::string>& files_a,
+ const std::vector<std::string>& files_b,
+ htio2::Strand strand_r1_in_file,
+ htio2::Strand strand_r2_in_file,
+ htio2::CompressFormat comp)
+: files_a(files_a)
+, files_b(files_b)
+, fh(new htio2::PairedEndIO(files_a[0],
+ files_b[0],
+ htio2::READ,
+ strand_r1_in_file,
+ strand_r2_in_file,
+ comp,
+ htio2::FORMAT_UNKNOWN))
+, interleave(false)
+, strand_r1_in_file(strand_r1_in_file)
+, strand_r2_in_file(strand_r2_in_file)
+, comp(comp)
+, curr_file_i(0)
+{
+}
+
+MultiSeqFilePE::~MultiSeqFilePE() {}
+
+bool MultiSeqFilePE::next_pair(htio2::FastqSeq& seq1,
+ htio2::FastqSeq& seq2,
+ htio2::Strand strand_r1,
+ htio2::Strand strand_r2)
+{
+ if (curr_file_i >= files_a.size())
+ return false;
+
+ while (true)
+ {
+ bool re = fh->next_pair(seq1, seq2, strand_r1, strand_r2);
+ if (re)
+ return true;
+
+ delete fh;
+ curr_file_i++;
+ if (curr_file_i >= files_a.size())
+ return false;
+
+ fh = interleave
+ ? new htio2::PairedEndIO(files_a[curr_file_i],
+ htio2::READ,
+ strand_r1_in_file,
+ strand_r2_in_file,
+ comp,
+ htio2::FORMAT_UNKNOWN)
+ : new htio2::PairedEndIO(files_a[curr_file_i],
+ files_b[curr_file_i],
+ htio2::READ,
+ strand_r1_in_file,
+ strand_r2_in_file,
+ comp,
+ htio2::FORMAT_UNKNOWN);
+ }
+}
+} // namespace htqc
+
diff --git a/src/htqc/MultiSeqFile.h b/src/htqc/MultiSeqFile.h
new file mode 100644
index 0000000..0d8a605
--- /dev/null
+++ b/src/htqc/MultiSeqFile.h
@@ -0,0 +1,75 @@
+#ifndef HTQC_MULTISEQFILEINPUT_H
+#define HTQC_MULTISEQFILEINPUT_H
+
+#include "htio2/PairedEndIO.h"
+#include "htio2/SeqIO.h"
+
+#include <vector>
+
+namespace htqc
+{
+
+class MultiSeqFileSE: public htio2::RefCounted
+{
+public:
+ typedef htio2::SmartPtr<MultiSeqFileSE> Ptr;
+ typedef htio2::SmartPtr<const MultiSeqFileSE> ConstPtr;
+
+public:
+ MultiSeqFileSE(const std::vector<std::string>& files, htio2::CompressFormat comp);
+ virtual ~MultiSeqFileSE();
+ bool next_seq(htio2::FastqSeq& seq);
+
+protected:
+ std::vector<std::string> files;
+ htio2::SeqIO::Ptr fh;
+ htio2::CompressFormat comp;
+ size_t curr_file_i;
+private:
+ MultiSeqFileSE(const MultiSeqFileSE& other);
+ MultiSeqFileSE& operator=(const MultiSeqFileSE& other);
+};
+
+class MultiSeqFilePE: public htio2::RefCounted
+{
+public:
+ typedef htio2::SmartPtr<MultiSeqFilePE> Ptr;
+ typedef htio2::SmartPtr<const MultiSeqFilePE> ConstPtr;
+
+public:
+ MultiSeqFilePE(const std::vector<std::string>& files,
+ htio2::Strand strand_r1_in_file,
+ htio2::Strand strand_r2_in_file,
+ htio2::CompressFormat comp);
+
+ MultiSeqFilePE(const std::vector<std::string>& files_a,
+ const std::vector<std::string>& files_b,
+ htio2::Strand strand_r1_in_file,
+ htio2::Strand strand_r2_in_file,
+ htio2::CompressFormat comp);
+ virtual ~MultiSeqFilePE();
+
+ bool next_pair(htio2::FastqSeq& seq1,
+ htio2::FastqSeq& seq2,
+ htio2::Strand strand_r1,
+ htio2::Strand strand_r2);
+
+protected:
+ std::vector<std::string> files_a;
+ std::vector<std::string> files_b;
+ size_t curr_file_i;
+ htio2::PairedEndIO* fh;
+
+ bool interleave;
+ htio2::Strand strand_r1_in_file;
+ htio2::Strand strand_r2_in_file;
+ htio2::CompressFormat comp;
+private:
+ MultiSeqFilePE(const MultiSeqFilePE& other);
+ MultiSeqFilePE& operator=(const MultiSeqFilePE& other);
+};
+
+} // namespace htqc
+
+#endif /* HTQC_MULTISEQFILEINPUT_H */
+
diff --git a/src/htqc/Options.cpp b/src/htqc/Options.cpp
new file mode 100644
index 0000000..a37e066
--- /dev/null
+++ b/src/htqc/Options.cpp
@@ -0,0 +1,337 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#define USE_file_out
+#define USE_prefix_out
+#define USE_se_pe
+#define USE_encode
+#define USE_header_format
+#define USE_mask
+#include "htqc/Options.h"
+#include "htio2/Cast.h"
+#include "htio2/Version.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FormatUtil.h"
+#include "htio2/HeaderUtil.h"
+#include "htio2/QualityUtil.h"
+
+using namespace std;
+using namespace htio2;
+
+namespace htqc
+{
+
+bool OPT_help;
+htio2::Option OPT_help_ENTRY("help", 'h', OPTION_GROUP_MISC,
+ &OPT_help, htio2::Option::FLAG_NONE,
+ "Show help.");
+
+vector<string> OPT_files_in;
+htio2::Option OPT_files_in_ENTRY("in", 'i', OPTION_GROUP_IO,
+ &OPT_files_in, htio2::Option::FLAG_MULTI_KEY, htio2::ValueLimit::Free(),
+ "Input files.", "FILE1 [FILE2 ...]");
+
+std::string OPT_prefix_out;
+htio2::Option OPT_prefix_out_ENTRY("out", 'o', OPTION_GROUP_IO,
+ &OPT_prefix_out, htio2::Option::FLAG_NONE,
+ "Output file prefix.", "FILE_PREFIX");
+
+htio2::QualityEncode OPT_encode(htio2::ENCODE_UNKNOWN);
+htio2::Option OPT_encode_ENTRY("encode", '\0', OPTION_GROUP_FORMAT,
+ &OPT_encode, htio2::Option::FLAG_NONE,
+ "Quality score encode.\n"
+ "sanger: 0 - 93 using ASCII 33 - 126\n"
+ "solexa: -5 - 62 using ASCII 59 - 126\n"
+ "illumina: 0 - 62 using ASCII 64 - 126\n"
+ "casava1.8: 0 - 62 using ASCII 33 - 95; 0 1 not used; values >40 rarely used",
+ "STRING");
+
+htio2::HeaderFormat OPT_header_format(htio2::HEADER_1_8);
+htio2::Option OPT_header_format_ENTRY("header-format", '\0', OPTION_GROUP_FORMAT,
+ &OPT_header_format, htio2::Option::FLAG_NONE,
+ "FASTQ header format.\n"
+ "casava1.8: produced by Illumina CASAVA version 1.8\n"
+ "pri_casava1.8: \tproduced by Illumina CASAVA version 1.7 or lower",
+ "STRING");
+
+bool OPT_header_sra(false);
+htio2::Option OPT_header_sra_ENTRY("header-sra", '\0', OPTION_GROUP_FORMAT,
+ &OPT_header_sra, htio2::Option::FLAG_NONE,
+ "Whether FASTQ header has NCBI SRA addon.");
+
+bool OPT_mask(false);
+htio2::Option OPT_mask_ENTRY("quality-mask", '\0', OPTION_GROUP_FORMAT,
+ &OPT_mask, htio2::Option::FLAG_NONE,
+ "Treat quality score 2 as a mask.");
+
+bool OPT_version(false);
+htio2::Option OPT_version_ENTRY("version", 'v', OPTION_GROUP_MISC,
+ &OPT_version, htio2::Option::FLAG_NONE,
+ "Show version.");
+
+bool OPT_quiet(false);
+htio2::Option OPT_quiet_ENTRY("quiet", 'q', OPTION_GROUP_MISC,
+ &OPT_quiet, htio2::Option::FLAG_NONE,
+ "Do not print information during program run.");
+
+bool OPT_se(false);
+htio2::Option OPT_se_ENTRY("se", 'S', OPTION_GROUP_FORMAT,
+ &OPT_se, htio2::Option::FLAG_NONE,
+ "Single-end reads.");
+bool OPT_pe(false);
+htio2::Option OPT_pe_ENTRY("pe", 'P', OPTION_GROUP_FORMAT,
+ &OPT_pe, htio2::Option::FLAG_NONE,
+ "Paired-end reads.");
+
+bool OPT_pe_itlv(false);
+htio2::Option OPT_pe_itlv_ENTRY("pe-itlv", '\0', OPTION_GROUP_FORMAT,
+ &OPT_pe_itlv, htio2::Option::FLAG_NONE,
+ "Paired-end reads are stored in interleaved format.");
+
+std::string _OPT_pe_strand("FR");
+htio2::Option OPT_pe_strand_ENTRY("pe-strand", '\0', OPTION_GROUP_FORMAT,
+ &_OPT_pe_strand, htio2::Option::FLAG_NONE,
+ "The strand of paired-end reads. \"F\" for forward, \"R\" for reverse. 1st character for read 1, 2nd character for read 2.",
+ "FF|FR|RF|RR");
+
+htio2::CompressFormat OPT_compress = htio2::COMPRESS_UNKNOWN;
+
+void show_files_in()
+{
+ cout << "# input files:" << endl;
+ if (OPT_se)
+ {
+ for (size_t i = 0; i < OPT_files_in.size(); i++)
+ cout << "# " << OPT_files_in[i] << endl;
+ }
+ else if (OPT_pe)
+ {
+ if (OPT_pe_itlv)
+ {
+ for (size_t i = 0; i < OPT_files_in.size(); i++)
+ cout << "# " << OPT_files_in[i] << endl;
+ }
+ else
+ {
+ if (OPT_files_in.size() % 2)
+ throw runtime_error("odd number of input files");
+ size_t hf_sz = OPT_files_in.size() / 2;
+ for (size_t i = 0; i < hf_sz; i++)
+ cout << "# " << OPT_files_in[i] << " and " << OPT_files_in[i + hf_sz] << endl;
+ }
+ }
+}
+
+void ensure_files_in()
+{
+ if (!OPT_files_in.size())
+ {
+ cerr << "ERROR: input files not specified" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_prefix_out()
+{
+ cout << "# output prefix: " << OPT_prefix_out << endl;
+}
+
+void ensure_prefix_out()
+{
+ tidy_prefix_out(OPT_prefix_out);
+ if (!OPT_prefix_out.length())
+ {
+ cerr << "ERROR: output file prefix not specified" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+htio2::Strand _cast_strand_chr(char value)
+{
+ switch (value)
+ {
+ case 'F':
+ case 'f':
+ return htio2::STRAND_FWD;
+ case 'R':
+ case 'r':
+ return htio2::STRAND_REV;
+ default:
+ cerr << "ERROR: invalid strand character representation: " << value << ". Only F/R/f/r allowed." << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+htio2::Strand OPT_pe_strand1()
+{
+ return _cast_strand_chr(_OPT_pe_strand[0]);
+}
+
+htio2::Strand OPT_pe_strand2()
+{
+ return _cast_strand_chr(_OPT_pe_strand[1]);
+}
+
+void show_se_pe()
+{
+ if (OPT_se)
+ {
+ cout << "# single-end" << endl;
+ }
+ else if (OPT_pe)
+ {
+ cout << "# paired-end" << endl;
+ if (OPT_pe_itlv)
+ cout << "# interleave file" << endl;
+ else
+ cout << "# file pair" << endl;
+ cout << "# strand: " << _OPT_pe_strand << endl;
+ }
+ else
+ {
+ cerr << "ERROR: neither single nor paired" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void ensure_se_pe()
+{
+ if ((OPT_se && OPT_pe) ||
+ !(OPT_se || OPT_pe))
+ {
+ cerr << "ERROR: single-end (--se, -S) or paired-end (--pe, -P)?" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (OPT_pe_itlv && !OPT_pe)
+ {
+ cerr << "WARNING: implicitly enabled paired-end mode, because interleave mode was selected" << endl;
+ OPT_pe = true;
+ }
+
+ if (_OPT_pe_strand.length() != 2
+ || !check_strand_chr(_OPT_pe_strand[0])
+ || !check_strand_chr(_OPT_pe_strand[1]))
+ {
+ cerr << "ERROR: invalid paired-end strand: \"" << _OPT_pe_strand << "\". Valid values: FF/FR/RF/RR (lower case allowed)." << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+void show_encode()
+{
+ cout << "# quality encode: " << htio2::to_string(OPT_encode) << endl;
+}
+
+void ensure_encode()
+{
+ if (OPT_encode == htio2::ENCODE_UNKNOWN)
+ {
+ if (!OPT_quiet) cout << "guess encode from front " << NUM_GUESS << " sequences of file " << OPT_files_in[0] << endl;
+
+ FastqIO fh(OPT_files_in[0], htio2::READ);
+ OPT_encode = guess_quality_encode(fh, NUM_GUESS);
+ if (OPT_encode == htio2::ENCODE_UNKNOWN)
+ {
+ cerr << "ERROR: failed to guess quality encode from input file " << OPT_files_in[0] << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (!OPT_quiet)
+ cout << "encode is: " << htio2::to_string(OPT_encode) << endl;
+ }
+}
+
+void show_header_format()
+{
+ cout << "# header format: " << htio2::to_string(OPT_header_format) << endl;
+}
+
+void ensure_header_format()
+{
+ if (OPT_header_format == htio2::HEADER_UNKNOWN)
+ {
+ if (!OPT_quiet) cout << "guess header format from front " << NUM_GUESS << " sequences of file " << OPT_files_in[0] << endl;
+ htio2::FastqIO fh(OPT_files_in[0], htio2::READ);
+ htio2::guess_header_format(fh, NUM_GUESS, OPT_header_format, OPT_header_sra);
+ if (OPT_header_format == htio2::HEADER_UNKNOWN)
+ {
+ cerr << "ERROR: failed to guess header format from input file " << OPT_files_in[0] << endl;
+ exit(EXIT_FAILURE);
+ }
+ if (!OPT_quiet)
+ {
+ cout << "header format is " << to_string(OPT_header_format);
+ if (OPT_header_sra) cout << ", with SRA" << endl;
+ else cout << ", without SRA" << endl;
+ }
+ }
+}
+
+void show_mask()
+{
+ cout << "# quality has mask: " << bool_to_string(OPT_mask) << endl;
+}
+
+htio2::CompressFormat guess_compress_format_by_files_name(const std::vector<std::string>& files)
+{
+ htio2::CompressFormat comp = htio2::COMPRESS_UNKNOWN;
+ string prev_file;
+ for (size_t i=0; i<files.size(); i++)
+ {
+ htio2::CompressFormat curr_comp = guess_compress_by_name(files[i]);
+
+ if (curr_comp == htio2::COMPRESS_UNKNOWN)
+ continue;
+
+ if (comp == htio2::COMPRESS_UNKNOWN)
+ {
+ comp = curr_comp;
+ prev_file = files[i];
+ }
+ else
+ {
+ if (comp != curr_comp)
+ {
+ cerr << "ERROR: conflict compress format by \"" << prev_file << "\" and \"" << files[i] << "\"" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ return comp;
+}
+
+void tidy_prefix_out(std::string & prefix)
+{
+ remove_suffix(prefix, ".gz");
+ remove_suffix(prefix, ".fq");
+ remove_suffix(prefix, ".fastq");
+}
+
+void show_version_and_exit()
+{
+ cout << htio2::get_version_string() << endl;
+ exit(EXIT_SUCCESS);
+}
+
+void remove_suffix(std::string& name, const std::string & suffix)
+{
+ size_t suffix_pos = name.rfind(suffix);
+ if (suffix_pos != string::npos)
+ name.erase(suffix_pos);
+}
+
+} // namespace htqc
diff --git a/src/htqc/Options.h b/src/htqc/Options.h
new file mode 100644
index 0000000..e63bae4
--- /dev/null
+++ b/src/htqc/Options.h
@@ -0,0 +1,121 @@
+// HTQC - a high-throughput sequencing quality control toolkit
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HTQC_OPTIONS_H
+#define HTQC_OPTIONS_H
+
+#include "htqc/Common.h"
+#include "htio2/QualityUtil.h"
+#include "htio2/HeaderUtil.h"
+#include "htio2/OptionParser.h"
+
+
+namespace htqc
+{
+
+#define OPTION_GROUP_IO "Input/Output Options"
+#define OPTION_GROUP_MISC "Miscellaneous Options"
+#define OPTION_GROUP_FORMAT "Sequence Format Options"
+
+extern std::vector<std::string> OPT_files_in;
+extern htio2::Option OPT_files_in_ENTRY;
+void show_files_in();
+void ensure_files_in();
+
+
+#ifdef USE_prefix_out
+extern std::string OPT_prefix_out;
+extern htio2::Option OPT_prefix_out_ENTRY;
+void show_prefix_out();
+void ensure_prefix_out();
+#endif
+
+#ifdef USE_se_pe
+extern bool OPT_se;
+extern bool OPT_pe;
+extern bool OPT_pe_itlv;
+extern std::string _OPT_pe_strand;
+
+extern htio2::Option OPT_se_ENTRY;
+extern htio2::Option OPT_pe_ENTRY;
+extern htio2::Option OPT_pe_itlv_ENTRY;
+extern htio2::Option OPT_pe_strand_ENTRY;
+
+htio2::Strand _cast_strand_chr(char value);
+htio2::Strand OPT_pe_strand1();
+htio2::Strand OPT_pe_strand2();
+
+
+inline bool check_strand_chr(char value)
+{
+ switch (value)
+ {
+ case 'F':
+ case 'f':
+ case 'R':
+ case 'r':
+ return true;
+ default:
+ return false;
+ }
+}
+
+void show_se_pe();
+void ensure_se_pe();
+#endif
+
+#ifdef USE_encode
+extern htio2::QualityEncode OPT_encode;
+extern bool OPT_mask;
+extern htio2::Option OPT_encode_ENTRY;
+extern htio2::Option OPT_mask_ENTRY;
+void show_encode();
+void ensure_encode();
+void show_mask();
+#endif
+
+#ifdef USE_header_format
+extern htio2::HeaderFormat OPT_header_format;
+extern bool OPT_header_sra;
+extern htio2::Option OPT_header_format_ENTRY;
+extern htio2::Option OPT_header_sra_ENTRY;
+void show_header_format();
+void ensure_header_format();
+#endif
+
+extern bool OPT_quiet;
+extern htio2::Option OPT_quiet_ENTRY;
+
+extern htio2::CompressFormat OPT_compress;
+htio2::CompressFormat guess_compress_format_by_files_name(const std::vector<std::string>& files);
+
+extern bool OPT_help;
+extern htio2::Option OPT_help_ENTRY;
+
+extern bool OPT_version;
+extern htio2::Option OPT_version_ENTRY;
+
+void tidy_prefix_out(std::string& prefix);
+
+void show_version_and_exit();
+
+void separate_paired_files(const std::vector<std::string>& in, std::vector<std::string>& names_a, std::vector<std::string>& names_b);
+
+void remove_suffix(std::string& name, const std::string& suffix);
+
+} // namespace htqc
+
+#endif /* HTQC_OPTIONS_H */
+
diff --git a/src/htqc/Primer.cpp b/src/htqc/Primer.cpp
new file mode 100644
index 0000000..922738d
--- /dev/null
+++ b/src/htqc/Primer.cpp
@@ -0,0 +1,127 @@
+#include "htqc/Primer.h"
+
+#include "htio2/SimpleSeq.h"
+
+using namespace std;
+
+namespace htqc
+{
+
+Primer::Primer(const std::string& id, const std::string& seq, size_t k)
+ : id(id)
+ , seq_fwd(seq)
+{
+ htio2::revcom(seq_fwd, seq_rev);
+ htio2::EncodedSeq enc_fwd;
+ htio2::EncodedSeq enc_rev;
+ htio2::encode_nt5(seq_fwd, enc_fwd);
+ htio2::encode_nt5(seq_rev, enc_rev);
+ htio2::gen_kmer_nt5(enc_fwd, klist_fwd, k);
+ htio2::gen_kmer_nt5(enc_rev, klist_rev, k);
+ htio2::summ_kmer_pos(klist_fwd, kpos_fwd);
+ htio2::summ_kmer_pos(klist_rev, kpos_rev);
+}
+
+bool align_primer(const string& read, const vector<int16_t>& read_qual, const KmerList& seq_km_list,
+ const string& primer, const KmerList& primer_km_list, const KmerPosMap& primer_km_pos,
+ int cut_qual, int cut_mis_high, int cut_mis_total,
+ PosT& seq_start, PosT& seq_end,
+ PosT& primer_start, PosT& primer_end)
+{
+ const size_t len_seq = read.length();
+ const size_t len_primer = primer.length();
+ const size_t nk_seq = seq_km_list.size();
+
+ bool success = false;
+
+ // traverse sequence kmer position
+ for (PosT i_seq_km = 0; i_seq_km < nk_seq; i_seq_km++)
+ {
+ const KmerT seq_km = seq_km_list[i_seq_km];
+ pair<KmerPosMap::const_iterator, KmerPosMap::const_iterator> primer_km_pos_bound = primer_km_pos.equal_range(seq_km);
+
+ // traverse primer kmer position
+ for (KmerPosMap::const_iterator primer_km_pos_it = primer_km_pos_bound.first;
+ primer_km_pos_it != primer_km_pos_bound.second;
+ primer_km_pos_it++)
+ {
+ const PosT i_primer_km = primer_km_pos_it->second;
+
+ const size_t len_seq_before = i_seq_km;
+ const size_t len_primer_before = i_primer_km;
+
+ // i_primer = i_seq + offset
+ const PosT offset = i_primer_km - i_seq_km;
+
+ // get alignment start position
+ PosT i_seq_start = 0;
+ PosT i_primer_start = 0;
+ if (len_seq_before < len_primer_before)
+ i_primer_start = i_seq_start + offset;
+ else
+ i_seq_start = i_primer_start - offset;
+
+ // traverse bases
+ PosT i_seq_end = i_seq_start;
+ PosT i_primer_end = i_primer_start;
+
+ uint16_t mis_high = 0;
+ uint16_t mis_total = 0;
+
+ while (1)
+ {
+ if (read[i_seq_end] != primer[i_primer_end])
+ {
+ mis_total++;
+ if (read_qual[i_seq_end] >= cut_qual)
+ mis_high++;
+ }
+
+ i_seq_end++;
+ i_primer_end++;
+ if (i_seq_end == len_seq || i_primer_end == len_primer) break;
+ }
+
+ // check status
+ if (mis_high <= cut_mis_high && mis_total <= cut_mis_total)
+ {
+ success = true;
+ seq_start = i_seq_start;
+ seq_end = i_seq_end - 1;
+ primer_start = i_primer_start;
+ primer_end = i_primer_end - 1;
+ break;
+ }
+ }
+
+ if (success) break;
+ }
+
+ return success;
+}
+
+bool Primer::align_fwd(const std::string &seq, const std::vector<int16_t> qual, const KmerList &seq_kmer,
+ int cut_qual, int cut_mis_high, int cut_mis_total,
+ PosT &seq_start, PosT &seq_end, PosT &primer_start, PosT &primer_end) const
+{
+ return align_primer(seq, qual, seq_kmer,
+ seq_fwd, klist_fwd, kpos_fwd,
+ cut_qual, cut_mis_high, cut_mis_total,
+ seq_start, seq_end,
+ primer_start, primer_end);
+}
+
+bool Primer::align_rev(const std::string &seq, const std::vector<int16_t> qual, const KmerList &seq_kmer,
+ int cut_qual, int cut_mis_high, int cut_mis_total,
+ PosT &seq_start, PosT &seq_end, PosT &primer_start, PosT &primer_end) const
+{
+ return align_primer(seq, qual, seq_kmer,
+ seq_rev, klist_rev, kpos_rev,
+ cut_qual, cut_mis_high, cut_mis_total,
+ seq_start, seq_end,
+ primer_start, primer_end);
+}
+
+PrimerGroup::PrimerGroup(const string &name): name(name) {}
+
+} // namespace htqc
diff --git a/src/htqc/Primer.h b/src/htqc/Primer.h
new file mode 100644
index 0000000..b2435c0
--- /dev/null
+++ b/src/htqc/Primer.h
@@ -0,0 +1,47 @@
+#ifndef PRIMER_H
+#define PRIMER_H
+
+#include "htio2/Kmer.h"
+
+namespace htqc
+{
+
+typedef uint32_t KmerT;
+typedef int16_t PosT;
+typedef std::vector<KmerT> KmerList;
+typedef std::multimap<KmerT, PosT> KmerPosMap;
+
+struct Primer
+{
+ Primer(const std::string& id, const std::string& seq, size_t k);
+
+ size_t length() const { return seq_fwd.length(); }
+ bool align_fwd(const std::string& seq, const std::vector<int16_t> qual, const KmerList& seq_kmer,
+ int cut_qual, int cut_mis_high, int cut_mis_total,
+ PosT& seq_start, PosT& seq_end,
+ PosT& primer_start, PosT& primer_end) const;
+ bool align_rev(const std::string& seq, const std::vector<int16_t> qual, const KmerList& seq_kmer,
+ int cut_qual, int cut_mis_high, int cut_mis_total,
+ PosT& seq_start, PosT& seq_end,
+ PosT& primer_start, PosT& primer_end) const;
+
+ std::string id;
+ std::string seq_fwd;
+ std::string seq_rev;
+ KmerList klist_fwd;
+ KmerList klist_rev;
+ KmerPosMap kpos_fwd;
+ KmerPosMap kpos_rev;
+};
+
+struct PrimerGroup
+{
+ PrimerGroup(const std::string& name);
+ std::string name;
+ std::vector<Primer> primers_left;
+ std::vector<Primer> primers_right;
+};
+
+} // namespace htqc
+
+#endif // PRIMER_H
diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt
new file mode 100644
index 0000000..6ca515a
--- /dev/null
+++ b/t/CMakeLists.txt
@@ -0,0 +1,275 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+configure_file(TestConfig.h.in TestConfig.h ESCAPE_QUOTES)
+
+add_library(TestFramework TestFramework.cpp)
+
+add_executable(t_text_file_equal t_text_file_equal.cpp)
+target_link_libraries(t_text_file_equal
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(text_file_equal t_text_file_equal)
+
+add_executable(t_kmer_nt5_16 t_kmer_nt5_16.cpp)
+target_link_libraries(t_kmer_nt5_16
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt5_16 t_kmer_nt5_16)
+
+add_executable(t_kmer_nt5_32 t_kmer_nt5_32.cpp)
+target_link_libraries(t_kmer_nt5_32
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt5_32 t_kmer_nt5_32)
+
+add_executable(t_kmer_nt5_64 t_kmer_nt5_64.cpp)
+target_link_libraries(t_kmer_nt5_64
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt5_64 t_kmer_nt5_64)
+
+add_executable(t_kmer_nt4_16 t_kmer_nt4_16.cpp)
+target_link_libraries(t_kmer_nt4_16
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt4_16 t_kmer_nt4_16)
+
+add_executable(t_kmer_nt4_32 t_kmer_nt4_32.cpp)
+target_link_libraries(t_kmer_nt4_32
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt4_32 t_kmer_nt4_32)
+
+add_executable(t_kmer_nt4_64 t_kmer_nt4_64.cpp)
+target_link_libraries(t_kmer_nt4_64
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_nt4_64 t_kmer_nt4_64)
+
+add_executable(t_kmer_aa t_kmer_aa.cpp)
+target_link_libraries(t_kmer_aa
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(kmer_aa t_kmer_aa)
+
+add_executable(t_ref_counted t_ref_counted.cpp)
+target_link_libraries(t_ref_counted
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ref_counted t_ref_counted)
+
+add_executable(t_simple_seq t_simple_seq.cpp)
+target_link_libraries(t_simple_seq
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(simple_seq t_simple_seq)
+
+add_executable(t_plain_file_handle t_plain_file_handle.cpp)
+target_link_libraries(t_plain_file_handle
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(plain_file_handle t_plain_file_handle)
+
+add_executable(t_gzip_file_handle t_gzip_file_handle.cpp)
+target_link_libraries(t_gzip_file_handle
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(gzip_file_handle t_gzip_file_handle)
+
+add_executable(t_fastq_io t_fastq_io.cpp)
+target_link_libraries(t_fastq_io
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(fastq_io t_fastq_io)
+
+add_executable(t_fasta_io t_fasta_io.cpp)
+target_link_libraries(t_fasta_io
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(fasta_io t_fasta_io)
+
+add_executable(t_header_util t_header_util.cpp)
+target_link_libraries(t_header_util
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(header_util t_header_util)
+
+add_executable(t_multi_seq_file_se t_multi_seq_file_se.cpp)
+target_link_libraries(t_multi_seq_file_se
+ TestFramework
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(multi_seq_file_se t_multi_seq_file_se)
+
+add_executable(t_multi_seq_file_pe t_multi_seq_file_pe.cpp)
+target_link_libraries(t_multi_seq_file_pe
+ TestFramework
+ ht_common
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(multi_seq_file_pe t_multi_seq_file_pe)
+
+add_executable(t_ht_sample t_ht_sample.cpp)
+target_link_libraries(t_ht_sample
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_sample t_ht_sample)
+
+add_executable(t_ht_trim t_ht_trim.cpp)
+target_link_libraries(t_ht_trim
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_trim t_ht_trim)
+
+add_executable(t_ht_rename t_ht_rename.cpp)
+target_link_libraries(t_ht_rename
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_rename t_ht_rename)
+
+add_executable(t_ht_overlap t_ht_overlap.cpp)
+target_link_libraries(t_ht_overlap
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_overlap t_ht_overlap)
+
+add_executable(t_ht_filter t_ht_filter.cpp)
+target_link_libraries(t_ht_filter
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_filter t_ht_filter)
+
+add_executable(t_ht_convert t_ht_convert.cpp)
+target_link_libraries(t_ht_convert
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_convert t_ht_convert)
+
+add_executable(t_ht_demul t_ht_demul.cpp)
+target_link_libraries(t_ht_demul
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_demul t_ht_demul)
+
+add_executable(t_ht_lane_tile t_ht_lane_tile.cpp)
+target_link_libraries(t_ht_lane_tile
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ht_lane_tile t_ht_lane_tile)
+
+add_executable(t_string t_string.cpp)
+target_link_libraries(t_string
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(string t_string)
+
+add_executable(t_cast t_cast.cpp)
+target_link_libraries(t_cast
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(cast t_cast)
+
+add_executable(option_parser option_parser.cpp)
+target_link_libraries(option_parser
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+
+add_executable(t_ring_buffer t_ring_buffer.cpp)
+target_link_libraries(t_ring_buffer
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(ring_buffer t_ring_buffer)
+
+add_executable(t_mt19937 t_mt19937.cpp)
+target_link_libraries(t_mt19937
+ TestFramework
+ htio2
+ ${juce_dep_libs}
+ ${ZLIB_LIBRARIES}
+)
+add_test(mt19937 t_mt19937)
+
diff --git a/t/TestConfig.h.in b/t/TestConfig.h.in
new file mode 100644
index 0000000..bba6c5e
--- /dev/null
+++ b/t/TestConfig.h.in
@@ -0,0 +1,6 @@
+#ifndef TESTCONFIG_H_IN
+#define TESTCONFIG_H_IN
+
+#define TEST_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
+
+#endif // TESTCONFIG_H_IN
diff --git a/t/TestFramework.cpp b/t/TestFramework.cpp
new file mode 100644
index 0000000..62f16a8
--- /dev/null
+++ b/t/TestFramework.cpp
@@ -0,0 +1,164 @@
+#include "TestFramework.h"
+#include "htio2/SeqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/PlainFileHandle.h"
+#include "htio2/GzipFileHandle.h"
+
+#include <iostream>
+
+using namespace std;
+
+TestFramework::TestFramework(): n_planned(0), n_got(0), n_fail(0)
+{
+}
+
+TestFramework::TestFramework(size_t n_tests): n_planned(n_tests), n_got(0), n_fail(0)
+{
+ if (!n_tests)
+ {
+ cerr << "zero number of planned tests" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+TestFramework::~TestFramework()
+{
+}
+
+bool TestFramework::run()
+{
+ content();
+ if (n_planned && n_planned != n_got)
+ {
+ cerr << "planned " << n_planned << ", but only run " << n_got << endl;
+ return false;
+ }
+ else
+ {
+ cout << n_got << " tests, " << n_fail << " failed" << endl;
+ return (n_fail == 0);
+ }
+}
+
+void TestFramework::ok(bool value, const char *desc)
+{
+ n_got++;
+ if (value)
+ {
+ cout << "ok " << n_got << " - " << desc << endl;
+ }
+ else
+ {
+ cout << "NOT ok " << n_got << " - " << desc << endl;
+ n_fail++;
+ }
+}
+
+bool text_file_eq(const char* file1, const char* file2)
+{
+ string _file1_(file1);
+ string _file2_(file2);
+ bool success = true;
+
+ htio2::FileHandle::Ptr fh1 = NULL;
+ htio2::FileHandle::Ptr fh2 = NULL;
+
+ if (_file1_.rfind(".gz") == _file1_.length()-3)
+ fh1 = new htio2::GzipFileHandle(_file1_, htio2::READ);
+ else
+ fh1 = new htio2::PlainFileHandle(_file1_, htio2::READ);
+
+ if (_file2_.rfind(".gz") == _file2_.length()-3)
+ fh2 = new htio2::GzipFileHandle(_file2_, htio2::READ);
+ else
+ fh2 = new htio2::PlainFileHandle(_file2_, htio2::READ);
+
+ string line1;
+ string line2;
+
+ while (1)
+ {
+ bool re1 = fh1->read_line(line1);
+ bool re2 = fh2->read_line(line2);
+ if (re1)
+ {
+ if (!re2)
+ {
+ success = false;
+ break;
+ }
+ }
+ else
+ {
+ if (re2)
+ {
+ success = false;
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (line1 != line2)
+ {
+ success = false;
+ break;
+ }
+ }
+
+ return success;
+}
+
+bool seq_file_id_eq(const char* file1, const char* file2)
+{
+ htio2::SeqIO::Ptr fh1(htio2::SeqIO::New(file1, htio2::READ));
+ htio2::SeqIO::Ptr fh2(htio2::SeqIO::New(file2, htio2::READ));
+
+ htio2::FastqSeq seq1, seq2;
+
+
+ bool success = true;
+ while (1)
+ {
+ bool re1 = fh1->next_seq(seq1);
+ bool re2 = fh2->next_seq(seq2);
+
+ if (re1)
+ {
+ if (!re2)
+ {
+ success = false;
+ break;
+ }
+ }
+ else
+ {
+ if (re2)
+ {
+ success = false;
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (seq1.id != seq2.id)
+ {
+ success = false;
+ break;
+ }
+ }
+
+ return success;
+}
+
+int main(int argc, char** argv)
+{
+ TestFramework t;
+ bool t_re = t.run();
+ exit(!t_re);
+}
diff --git a/t/TestFramework.h b/t/TestFramework.h
new file mode 100644
index 0000000..be204f8
--- /dev/null
+++ b/t/TestFramework.h
@@ -0,0 +1,155 @@
+#ifndef HTQC_TEST_FRAMEWORK
+#define HTQC_TEST_FRAMEWORK
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <iostream>
+#include <cmath>
+
+#include "htio2/StringUtil.h"
+
+#define OK(arg) ok(arg, EXPAND_AND_STRINGIFY(arg))
+#define IS(arg1, arg2) is(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " == " EXPAND_AND_STRINGIFY(arg2))
+#define IS_EPSILON(arg1, arg2) is_epsilon(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " ~~ " EXPAND_AND_STRINGIFY(arg2))
+#define GT(arg1, arg2) gt(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " > " EXPAND_AND_STRINGIFY(arg2))
+#define GE(arg1, arg2) ge(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " >= " EXPAND_AND_STRINGIFY(arg2))
+#define LT(arg1, arg2) lt(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " < " EXPAND_AND_STRINGIFY(arg2))
+#define LE(arg1, arg2) le(arg1, arg2, EXPAND_AND_STRINGIFY(arg1) " <= " EXPAND_AND_STRINGIFY(arg2))
+
+class TestFramework
+{
+public:
+ TestFramework();
+ TestFramework(size_t n_tests);
+ ~TestFramework();
+
+ void ok(bool value, const char* desc);
+
+ template<typename T1, typename T2>
+ void is(T1 value, T2 expect, const char* desc);
+
+ template<typename T>
+ void is_epsilon(T value, T expect, const char* desc, T rate = 10000);
+
+ template<typename T1, typename T2>
+ void gt(T1 a, T2 b, const char* desc);
+
+ template<typename T1, typename T2>
+ void ge(T1 a, T2 b, const char* desc);
+
+ template<typename T1, typename T2>
+ void lt(T1 a, T2 b, const char* desc);
+
+ template<typename T1, typename T2>
+ void le(T1 a, T2 b, const char* desc);
+
+ bool run();
+
+protected:
+ void content();
+ size_t n_planned;
+ size_t n_got;
+ size_t n_fail;
+};
+
+bool text_file_eq(const char* file1, const char* file2);
+bool seq_file_id_eq(const char* file1, const char* file2);
+
+template<typename T1, typename T2>
+void TestFramework::is(T1 value, T2 expect, const char* desc)
+{
+ n_got++;
+ if (value == expect)
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ <<" got " << value <<", expect "<< expect << " " << std::endl;
+ n_fail++;
+ }
+}
+
+template<typename T>
+void TestFramework::is_epsilon(T value, T expect, const char* desc, T rate)
+{
+ n_got++;
+ if (std::abs(value-expect) <= std::abs(expect/rate))
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ <<" got " << value <<", expect "<< expect << " " << std::endl;
+ n_fail++;
+ }
+}
+
+template<typename T1, typename T2>
+void TestFramework::gt(T1 a, T2 b, const char* desc)
+{
+ n_got++;
+ if (a > b)
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ << " got " << a << " and " << b << std::endl;
+ n_fail++;
+ }
+}
+
+template<typename T1, typename T2>
+void TestFramework::ge(T1 a, T2 b, const char* desc)
+{
+ n_got++;
+ if (a >= b)
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ << " got " << a << " and " << b << std::endl;
+ n_fail++;
+ }
+}
+
+template<typename T1, typename T2>
+void TestFramework::lt(T1 a, T2 b, const char* desc)
+{
+ n_got++;
+ if (a < b)
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ << " got " << a << " and " << b << std::endl;
+ n_fail++;
+ }
+}
+
+template<typename T1, typename T2>
+void TestFramework::le(T1 a, T2 b, const char* desc)
+{
+ n_got++;
+ if (a <= b)
+ {
+ std::cout << "ok " << n_got << " - " << desc << std::endl;
+ }
+ else
+ {
+ std::cout << "NOT ok " << n_got << " - " << desc << std::endl
+ << " got " << a << " and " << b << std::endl;
+ n_fail++;
+ }
+}
+
+#endif
diff --git a/t/barcodes.tab b/t/barcodes.tab
new file mode 100644
index 0000000..639d45e
--- /dev/null
+++ b/t/barcodes.tab
@@ -0,0 +1,66 @@
+Bgenome XB-47 CCGTCC
+plasmid E161p-1 TACAGC
+plasmid E161p-4 TCATTC
+plasmid E31p-7 TCGAAG
+plasmid S13p-5 TCGGCA
+plasmid E31p-6 ATGTCA
+16S_PCR gut_20 TAGCTT
+16S_PCR.Plasmid-All gut_23.S13p CTTGTA
+16S_PCR gut_25 AGTACG
+16S_PCR gut_27 TCAGTC
+16S_PCR gut_29 TTGAGC
+16S_PCR gut_31 AAGCGA
+16S_PCR gut_33 TCCTCA
+16S_PCR gut_35 GGTTGT
+16S_PCR gut_38 TGAGGT
+16S_PCR.Meta gut_1.gut-37 ATCACG
+16S_PCR gut_41 AGAGAG
+16S_PCR gut_43 CACTTG
+16S_PCR gut_47 AGTGGT
+16S_PCR gut_50 GGATAA
+16S_PCR gut_51 GTTGAA
+16S_PCR gut_53 CGAATA
+16S_PCR gut_55 TTGGTA
+16S_PCR.Bgenome gut_3.XB-49 CGATGT
+16S_PCR gut_57 CATCTA
+16S_PCR gut_83 CTCAAT
+16S_PCR gut_85 TGGATT
+16S_PCR gut_87 AGTGTT
+16S_PCR gut_90 CAATGT
+16S_PCR gut_91 ACTTCT
+16S_PCR gut_94 AAGATG
+16S_PCR gut_59 TAATCG
+16S_PCR gut_95 ATACAC
+16S_PCR.Meta gut_5.gut-52 TTAGGC
+16S_PCR gut_63 CTGTCA
+16S_PCR gut_66 GAACCT
+16S_PCR gut_67 AAGTCC
+16S_PCR gut_69 CGCTGA
+16S_PCR gut_71 GGCCTT
+16S_PCR gut_97 GTCGCT
+16S_PCR gut_99 CTACGG
+16S_PCR gut_74 CAGCAC
+16S_PCR gut_103 CCTTAA
+16S_PCR.Bgenome gut_8.XB-51 TGACCA
+16S_PCR gut_34 CAAGAA
+16S_PCR gut_52 TCACAA
+16S_PCR gut_106 CGTCAA
+16S_PCR gut_89 GACACT
+16S_PCR gut_110 CCTTCT
+16S_PCR gut_9 ACAGTG
+16S_PCR.plasmid gut_11.E161p-6 GCCAAT
+16S_PCR.Bgenome gut_14.E161 CAGATC
+16S_PCR.Bgenome gut_15.E31 ACTTGA
+16S_PCR gut_17 GATCAG
+ITS_PCR ITS_3 GCCTAA
+ITS_PCR ITS_4 TGGTCA
+ITS_PCR ITS_13_1 TTGACT
+ITS_PCR ITS_14_1 GGAACT
+ITS_PCR ITS_15_1 TGACAT
+ITS_PCR ITS_16_1 GGACGG
+ITS_PCR ITS_18_1 TTTCAC
+ITS_PCR ITS_21_1 CGTACG
+ITS_PCR ITS_23_1 ATCAGT
+ITS_PCR ITS_10 AAGCTA
+ITS_PCR ITS_19 GGCCAC
+ITS_PCR ITS_22 CCACTC
diff --git a/t/double_1.fastq b/t/double_1.fastq
new file mode 100644
index 0000000..d1058bc
--- /dev/null
+++ b/t/double_1.fastq
@@ -0,0 +1,8 @@
+ at HISEQ:478:HB47HADXX:1:2111:14982:13660 1:N:0:CGATGT
+TGAGGAATCTTGCGCAATGGGGGAAACCCTGACGCAGCAACGCCGCGTGAGTGAGGAAGGTCTTCGGATCGTAAAGCTCTGTCAGATGGGAAGAAATGCCTGGGGGTTAATAGCCCCTCTGCTTGACGGTAC
++
+AG9DGFFAF?DFFFIDD?BFD(;@EFEEAEDBBD>C>BB;<B at B<@@BBB<4>>@?BBBBABBABBBBB at 5<@<BBBBAA>>:4:BBAB19A@?BBBBBBBBBBBB>>BBEE at A@B>?BB3(4>>@BB9<@B
+ at HISEQ:478:HB47HADXX:1:2111:15037:13522 1:N:0:CGATGT
+CAGTTAGGAATTTTGCGCAATGGACGAAAGTCTGACGCAGCGACATCGCGTGTGGGATGACAGCCTTAGGGTTGTAAACCACTTTTTGGGAGCCATGAAGGCGCCCAGAATAAGGAACTACTAACTACGTG
++
+IGJIGIIIJIJJJJJJJJGIIJGJJJJJIJEHHHHHFFDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCBDDDDEDDDDDDDDDBBDABDDDDDDDDABBDDDDDDDDDDCDCDDCDDDDDDDDDBDD
diff --git a/t/double_2.fastq b/t/double_2.fastq
new file mode 100644
index 0000000..bad308d
--- /dev/null
+++ b/t/double_2.fastq
@@ -0,0 +1,8 @@
+ at HISEQ:478:HB47HADXX:1:2111:14982:13660 2:N:0:CGATGT
+CACGGAGTTAGCCGGTGCTTCCTCTGATGGTACCGTCAAGCAGAGGGGCTATTAACCCCCAGGCATTTCTTCCCATCTGACAGAGCTTTACGATCCGAAGACCTTCCTCACTCACGCGGCGTTGCTGCGTC
++
+CBFD<6?B*?DFH>@FHGEHEA;AEH=?CCD at DC<A?B:@@BCCBBBBBBBCCACCCBBBBBBBBCC at ACACACACCCCCCCACC>4>CCCBB<B<BB?59>CCCCCAAC?AC??BBBBBBBBBBCCCB59
+ at HISEQ:478:HB47HADXX:1:2111:15037:13522 2:N:0:CGATGT
+CACGTAGTTAGTAGTTCCTTATTCTGGGCGCCTTCATGGCTCCCAAAAAGTGGTTTACAACCCTAAGGCTGTCATCCCACACGCGATGTCGCTGCGTCAGACTTTCGTCCATTGCGCAAAATTCCTAACTGC
++
+JIJJJJJJJJIHIJJIJJJJIJJJJIIJJHJHHFFFFFEEEEDDDDDDDDCDDDDDDDDDDDBDDDDDDDBBDDDDDDDDDDDBBDDDACDDDDDDDDBDDDDDDDDDDDDEEDDBDDDDDDDDDDDDDDDD
diff --git a/t/double_ovlp.fastq b/t/double_ovlp.fastq
new file mode 100644
index 0000000..4a89973
Binary files /dev/null and b/t/double_ovlp.fastq differ
diff --git a/t/filt.fastq.gz b/t/filt.fastq.gz
new file mode 100644
index 0000000..7a3ba74
Binary files /dev/null and b/t/filt.fastq.gz differ
diff --git a/t/filt_1.fastq.gz b/t/filt_1.fastq.gz
new file mode 100644
index 0000000..5bbb150
Binary files /dev/null and b/t/filt_1.fastq.gz differ
diff --git a/t/filt_2.fastq.gz b/t/filt_2.fastq.gz
new file mode 100644
index 0000000..946f6df
Binary files /dev/null and b/t/filt_2.fastq.gz differ
diff --git a/t/filt_fail.fastq.gz b/t/filt_fail.fastq.gz
new file mode 100644
index 0000000..1e6637e
Binary files /dev/null and b/t/filt_fail.fastq.gz differ
diff --git a/t/filt_fail_1.fastq.gz b/t/filt_fail_1.fastq.gz
new file mode 100644
index 0000000..31f2f97
Binary files /dev/null and b/t/filt_fail_1.fastq.gz differ
diff --git a/t/filt_fail_2.fastq.gz b/t/filt_fail_2.fastq.gz
new file mode 100644
index 0000000..6a9d03c
Binary files /dev/null and b/t/filt_fail_2.fastq.gz differ
diff --git a/t/filt_fail_s.fastq.gz b/t/filt_fail_s.fastq.gz
new file mode 100644
index 0000000..2e40b91
Binary files /dev/null and b/t/filt_fail_s.fastq.gz differ
diff --git a/t/filt_s.fastq.gz b/t/filt_s.fastq.gz
new file mode 100644
index 0000000..58310ce
Binary files /dev/null and b/t/filt_s.fastq.gz differ
diff --git a/t/option_parser.cpp b/t/option_parser.cpp
new file mode 100644
index 0000000..c152976
--- /dev/null
+++ b/t/option_parser.cpp
@@ -0,0 +1,54 @@
+#include "htio2/OptionParser.h"
+
+#include <vector>
+#include <string>
+#include <iostream>
+
+using namespace std;
+using namespace htio2;
+
+
+int main(int argc, char** argv)
+{
+ bool opt1 = false;
+ string opt2 = "opt2_default";
+ vector<int> opt3;
+
+ Option opt1_entry("foo", 'f', "help doc group 1",
+ &opt1, Option::FLAG_NONE,
+ "boolean option foo the quick brown fox jumps over a lazy dog, the quick brown fox jumps over a lazy dog.");
+
+ Option opt2_entry("bar", '\0', "help doc group 2",
+ &opt2, Option::FLAG_NONE,
+ "string option bar", "STR");
+
+ Option opt3_entry("baz", 'b', "group2",
+ &opt3, Option::FLAG_NONE, ValueLimit::Fixed(3),
+ "int list option baz", "INT INT INT");
+
+ OptionParser parser;
+ parser.add_option(opt1_entry);
+ parser.add_option(opt2_entry);
+ parser.add_option(opt3_entry);
+ parser.parse_options(argc, argv);
+
+ cout << parser.format_document() << endl;
+ cout << "after parse" << endl
+ << " opt1: " << opt1 << endl
+ << " opt2: " << opt2 << endl
+ << " opt3: ";
+ for (size_t i=0; i< opt3.size(); i++)
+ {
+ cout << opt3[i] << " ";
+ }
+ cout << endl;
+
+ cout << "remaining options: " << argc << endl;
+ for (int i=0; i<argc; i++)
+ {
+ cout << " " << argv[i] << endl;
+ }
+}
+
+
+
diff --git a/t/primers.fasta b/t/primers.fasta
new file mode 100644
index 0000000..45f7b6a
--- /dev/null
+++ b/t/primers.fasta
@@ -0,0 +1,13 @@
+>left1 16S
+ACTCCTACGGGAGGCAG
+>left2 16S
+CTCCTACGGGAGGCAGC
+>left3 16S
+TCCTACGGGAGGCAGCA
+>left4 16S
+CCTACGGGAGGCAGCAG
+>left5 16S
+CTACGGGAGGCAGCAGT
+>right1 16S
+ATTACCGCGGCTGCTGG
+
diff --git a/t/single_1.fastq b/t/single_1.fastq
new file mode 100644
index 0000000..cefc352
--- /dev/null
+++ b/t/single_1.fastq
@@ -0,0 +1,4 @@
+ at HISEQ:478:HB47HADXX:1:2111:15037:13522 1:N:0:CGATGT
+CAGTTAGGAATTTTGCGCAATGGACGAAAGTCTGACGCAGCGACATCGCGTGTGGGATGACAGCCTTAGGGTTGTAAACCACTTTTTGGGAGCCATGAAGGCGCCCAGAATAAGGAACTACTAACTACGTG
++
+IGJIGIIIJIJJJJJJJJGIIJGJJJJJIJEHHHHHFFDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCBDDDDEDDDDDDDDDBBDABDDDDDDDDABBDDDDDDDDDDCDCDDCDDDDDDDDDBDD
diff --git a/t/single_2.fastq b/t/single_2.fastq
new file mode 100644
index 0000000..6304c88
--- /dev/null
+++ b/t/single_2.fastq
@@ -0,0 +1,4 @@
+ at HISEQ:478:HB47HADXX:1:2111:15037:13522 2:N:0:CGATGT
+CACGTAGTTAGTAGTTCCTTATTCTGGGCGCCTTCATGGCTCCCAAAAAGTGGTTTACAACCCTAAGGCTGTCATCCCACACGCGATGTCGCTGCGTCAGACTTTCGTCCATTGCGCAAAATTCCTAACTGC
++
+JIJJJJJJJJIHIJJIJJJJIJJJJIIJJHJHHFFFFFEEEEDDDDDDDDCDDDDDDDDDDDBDDDDDDDBBDDDDDDDDDDDBBDDDACDDDDDDDDBDDDDDDDDDDDDEEDDBDDDDDDDDDDDDDDDD
diff --git a/t/t_cast.cpp b/t/t_cast.cpp
new file mode 100644
index 0000000..585c581
--- /dev/null
+++ b/t/t_cast.cpp
@@ -0,0 +1,80 @@
+#include <TestConfig.h>
+#include <TestFramework.h>
+
+#include "htio2/Cast.h"
+#include "htio2/StringUtil.h"
+
+#include <limits.h>
+#include <limits>
+
+#include <sstream>
+
+using namespace htio2;
+using namespace std;
+
+#define FROM_STRING_TEST(__type__, __value__) {\
+ ostringstream tmp_input;\
+ tmp_input << " \t" << (__value__) << " ";\
+ __type__ tmp_output = 0;\
+ ok(from_string<__type__>(tmp_input.str(), tmp_output), ("cast \""+tmp_input.str()+"\"").c_str());\
+ IS(tmp_output, __value__);\
+ }\
+
+#define FROM_STRING_TEST_EPSILON(__type__, __value__, __epsilon__) {\
+ ostringstream tmp_input;\
+ tmp_input << " \t " << (__value__) << " ";\
+ __type__ tmp_output = 0;\
+ ok(from_string<__type__>(tmp_input.str(), tmp_output), ("cast \""+tmp_input.str()+"\"").c_str());\
+ is_epsilon(tmp_output, __value__, EXPAND_AND_STRINGIFY(tmp_output) " ~~ " EXPAND_AND_STRINGIFY(__value__), __epsilon__);\
+ }\
+
+#define FROM_STRING_TEST_ENUM(__type__, __input_str__, __value__) {\
+ __type__ tmp_output;\
+ ok(from_string<__type__>(__input_str__, tmp_output), (string("cast \"")+__input_str__+"\"").c_str());\
+ IS(tmp_output, __value__);\
+ }\
+
+void TestFramework::content()
+{
+ // integer types
+ FROM_STRING_TEST(short, SHRT_MIN);
+ FROM_STRING_TEST(short, SHRT_MAX);
+ FROM_STRING_TEST(int, INT_MIN);
+ FROM_STRING_TEST(int, INT_MAX);
+ FROM_STRING_TEST(long, LONG_MIN);
+ FROM_STRING_TEST(long, LONG_MAX);
+ FROM_STRING_TEST(long long, LONG_LONG_MIN);
+ FROM_STRING_TEST(long long, LONG_LONG_MAX);
+
+ FROM_STRING_TEST(unsigned short, 0);
+ FROM_STRING_TEST(unsigned short, USHRT_MAX);
+ FROM_STRING_TEST(unsigned int, 0);
+ FROM_STRING_TEST(unsigned int, UINT_MAX);
+ FROM_STRING_TEST(unsigned long, 0);
+ FROM_STRING_TEST(unsigned long, ULONG_MAX);
+ FROM_STRING_TEST(unsigned long long, 0);
+ FROM_STRING_TEST(unsigned long long, ULONG_LONG_MAX);
+
+ // floating point types
+ FROM_STRING_TEST_EPSILON(float, numeric_limits<float>::min(), 10000.0f);
+ FROM_STRING_TEST_EPSILON(float, numeric_limits<float>::max(), 10000.0f);
+ FROM_STRING_TEST_EPSILON(double, numeric_limits<double>::min(), 10000.0);
+ FROM_STRING_TEST_EPSILON(double, numeric_limits<double>::max(), 10000.0);
+
+ // enum types
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "unknown", htio2::COMPRESS_UNKNOWN);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "plain", htio2::COMPRESS_PLAIN);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "xz", htio2::COMPRESS_LZMA);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "lzma", htio2::COMPRESS_LZMA);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "gz", htio2::COMPRESS_GZIP);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "gzip", htio2::COMPRESS_GZIP);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "bz2", htio2::COMPRESS_BZIP2);
+ FROM_STRING_TEST_ENUM(htio2::CompressFormat, "bzip2", htio2::COMPRESS_BZIP2);
+
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fastq", htio2::FORMAT_FASTQ);
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fq", htio2::FORMAT_FASTQ);
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fasta", htio2::FORMAT_FASTA);
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fas", htio2::FORMAT_FASTA);
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fa", htio2::FORMAT_FASTA);
+ FROM_STRING_TEST_ENUM(htio2::SeqFormat, "fna", htio2::FORMAT_FASTA);
+}
diff --git a/t/t_fasta_io.cpp b/t/t_fasta_io.cpp
new file mode 100644
index 0000000..cedcc49
--- /dev/null
+++ b/t/t_fasta_io.cpp
@@ -0,0 +1,72 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htio2/SeqIO.h"
+#include "htio2/FastqSeq.h"
+#include <stdio.h>
+
+using namespace std;
+using namespace htio2;
+
+void TestFramework::content()
+{
+ htio2::SeqIO* fh = SeqIO::New(TEST_SOURCE_DIR"/test1.fasta", htio2::READ);
+
+ FastqSeq seq1;
+
+ off_t off1 = fh->tell();
+ IS(off1, 0);
+
+ OK(fh->next_seq(seq1));
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq1.quality, "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII");
+
+ FastqSeq seq2;
+
+ off_t off2 = fh->tell();
+ IS(off2, 209);
+
+ OK(fh->next_seq(seq2));
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1197:2208");
+ IS(seq2.desc, "1:N:0:TTGGTA");
+ IS(seq2.seq, "AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTGGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATNNTGACGGTACCTGACTAAGAAGCTCCGGCTAACTA");
+ IS(seq2.quality, "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII");
+
+ // absolute seek
+ {
+ FastqSeq seq;
+ fh->seek(off1);
+ OK(fh->next_seq(seq));
+ IS(seq.id, seq1.id);
+ IS(seq.desc, seq1.desc);
+ IS(seq.seq, seq1.seq);
+ IS(seq.quality, seq1.quality);
+ }
+
+ // relative seek
+ {
+ FastqSeq seq;
+ fh->seek(off1);
+ fh->seek(off2-off1, SEEK_CUR);
+ OK(fh->next_seq(seq));
+ IS(seq.id, seq2.id);
+ IS(seq.desc, seq2.desc);
+ IS(seq.seq, seq2.seq);
+ IS(seq.quality, seq2.quality);
+ }
+
+ // end seek
+ {
+ FastqSeq seq;
+ fh->seek(-209, SEEK_END);
+ OK(fh->next_seq(seq));
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq.desc, "1:N:0:TTAGGC");
+ IS(seq.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq.quality, "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII");
+ }
+
+ delete fh;
+}
+
diff --git a/t/t_fastq_io.cpp b/t/t_fastq_io.cpp
new file mode 100644
index 0000000..7c60d52
--- /dev/null
+++ b/t/t_fastq_io.cpp
@@ -0,0 +1,72 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htio2/SeqIO.h"
+#include "htio2/FastqSeq.h"
+#include <stdio.h>
+
+using namespace std;
+using namespace htio2;
+
+void TestFramework::content()
+{
+ htio2::SeqIO* fh = SeqIO::New(TEST_SOURCE_DIR"/test1.fastq", htio2::READ);
+
+ FastqSeq seq1;
+
+ off_t off1 = fh->tell();
+ IS(off1, 0);
+
+ OK(fh->next_seq(seq1));
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq1.quality, "=?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA?ABCAC at 9@AA8??8><ADB<>B8<B:C?>@>>34>:@CD");
+
+ FastqSeq seq2;
+
+ off_t off2 = fh->tell();
+ IS(off2, 360);
+
+ OK(fh->next_seq(seq2));
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1197:2208");
+ IS(seq2.desc, "1:N:0:TTGGTA");
+ IS(seq2.seq, "AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTGGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATNNTGACGGTACCTGACTAAGAAGCTCCGGCTAACTA");
+ IS(seq2.quality, "@@CFFDFFGHHHHJJHFHGHHGIIHIJJJJIHHJJJJGIGIJHIJGIICFC at ECEHAB@4=;@DBB8B at B:@:>C>>CCCD:?CDDDDBDEEEDCCDCDDCCCC@@ADD?BDBD##++8?@B9A9CDCCCCCDDCDCCD at C>BBDDCDDD");
+
+ // absolute seek
+ {
+ FastqSeq seq;
+ fh->seek(off1);
+ OK(fh->next_seq(seq));
+ IS(seq.id, seq1.id);
+ IS(seq.desc, seq1.desc);
+ IS(seq.seq, seq1.seq);
+ IS(seq.quality, seq1.quality);
+ }
+
+ // relative seek
+ {
+ FastqSeq seq;
+ fh->seek(off1);
+ fh->seek(off2-off1, SEEK_CUR);
+ OK(fh->next_seq(seq));
+ IS(seq.id, seq2.id);
+ IS(seq.desc, seq2.desc);
+ IS(seq.seq, seq2.seq);
+ IS(seq.quality, seq2.quality);
+ }
+
+ // end seek
+ {
+ FastqSeq seq;
+ fh->seek(-360, SEEK_END);
+ OK(fh->next_seq(seq));
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq.desc, "1:N:0:TTAGGC");
+ IS(seq.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ }
+
+ delete fh;
+}
+
diff --git a/t/t_gzip_file_handle.cpp b/t/t_gzip_file_handle.cpp
new file mode 100644
index 0000000..a80de54
--- /dev/null
+++ b/t/t_gzip_file_handle.cpp
@@ -0,0 +1,56 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htio2/GzipFileHandle.h"
+#include <stdio.h>
+
+
+using namespace std;
+using namespace htio2;
+
+void TestFramework::content()
+{
+ GzipFileHandle fh(TEST_SOURCE_DIR"/test1.fastq", htio2::READ);
+ string line1;
+ string line2;
+ string line3;
+ string line4;
+
+ OK(fh.read_line(line1));
+ off_t off1 = fh.tell();
+ OK(fh.read_line(line2));
+ off_t off2 = fh.tell();
+ OK(fh.read_line(line3));
+ off_t off3 = fh.tell();
+ OK(fh.read_line(line4));
+ off_t off4 = fh.tell();
+
+ IS(line1, "@HWI-ST1106:815:H154GADXX:1:1101:1244:2196 1:N:0:CTTGTA");
+ IS(off1, 56);
+ IS(line2, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(off2, 207);
+ IS(line3, "+");
+ IS(off3, 209);
+ IS(line4, "=?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA?ABCAC at 9@AA8??8><ADB<>B8<B:C?>@>>34>:@CD");
+ IS(off4, 360);
+ IS(gztell(fh.handle), 361);
+
+ fh.seek(off3, 0);
+ string line4again;
+ OK(fh.read_line(line4again));
+ IS(line4again, line4);
+
+ fh.seek(off1, 0);
+ string line2again;
+ OK(fh.read_line(line2again));
+ IS(line2again, line2);
+
+ fh.seek(off2, SEEK_SET);
+ fh.seek(off3-off2, SEEK_CUR);
+ IS(fh.tell(), off3);
+ IS(gztell(fh.handle), off3+1);
+ {
+ string line;
+ OK(fh.read_line(line));
+ IS(line, line4);
+ }
+}
diff --git a/t/t_header_util.cpp b/t/t_header_util.cpp
new file mode 100644
index 0000000..5452162
--- /dev/null
+++ b/t/t_header_util.cpp
@@ -0,0 +1,37 @@
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/HeaderUtil.h"
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+void TestFramework::content()
+{
+ htio2::FastqIO io(TEST_SOURCE_DIR"/test1.fastq", htio2::READ, htio2::COMPRESS_PLAIN);
+ htio2::FastqSeq seq;
+ OK(io.next_seq(seq));
+
+ htio2::HeaderFormat format = htio2::HEADER_UNKNOWN;
+ bool with_ncbi = false;
+ htio2::guess_header_format(seq.id+" "+seq.desc, format, with_ncbi);
+ IS(format, htio2::HEADER_1_8);
+ OK(!with_ncbi);
+
+ htio2::guess_header_format("SRR000000 "+seq.id+" "+seq.desc+" length=100", format, with_ncbi);
+ IS(format, htio2::HEADER_1_8);
+ OK(with_ncbi);
+
+ format = htio2::HEADER_UNKNOWN;
+ with_ncbi = false;
+ htio2::guess_header_format(io, 5, format, with_ncbi);
+ IS(format, htio2::HEADER_1_8);
+ OK(!with_ncbi);
+
+ {
+ htio2::HeaderParser header_parser(htio2::HEADER_1_8, false);
+ header_parser.parse(seq.id, seq.desc);
+ IS(header_parser.lane, 1);
+ IS(header_parser.tile, 1101);
+ IS(header_parser.barcode, "CTTGTA");
+ }
+
+}
diff --git a/t/t_ht_convert.cpp b/t/t_ht_convert.cpp
new file mode 100644
index 0000000..d2e1deb
--- /dev/null
+++ b/t/t_ht_convert.cpp
@@ -0,0 +1,17 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+void TestFramework::content()
+{
+ {
+ const char* cmd = "../src/ht2-convert -q -P --out-pe-itlv -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz -o interleave";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/test_interleave.fastq.gz", "interleave.fastq.gz"));
+ }
+ {
+ const char* cmd = "../src/ht2-convert -q -P --pe-itlv -i " TEST_SOURCE_DIR "/test_interleave.fastq.gz -o non_interleave";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/test1.fastq.gz", "non_interleave_1.fastq.gz"));
+ OK(text_file_eq(TEST_SOURCE_DIR "/test2.fastq.gz", "non_interleave_2.fastq.gz"));
+ }
+}
diff --git a/t/t_ht_demul.cpp b/t/t_ht_demul.cpp
new file mode 100644
index 0000000..b9751a0
--- /dev/null
+++ b/t/t_ht_demul.cpp
@@ -0,0 +1,126 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+#include "htio2/PlainFileHandle.h"
+#include "htio2/FastqSeq.h"
+#include "htio2/FastqIO.h"
+
+#include "htio2/JUCE-3.0.8/JuceHeader.h"
+
+#include <vector>
+#include <map>
+
+using namespace std;
+using namespace htio2::juce;
+
+#define FILE1 TEST_SOURCE_DIR "/test1.fastq.gz"
+#define FILE2 TEST_SOURCE_DIR "/test2.fastq.gz"
+#define BARCODE TEST_SOURCE_DIR "/barcodes.tab"
+
+typedef map<string, pair<string,string> > BarcodeMap;
+
+void read_barcode(BarcodeMap& barcodes)
+{
+ htio2::PlainFileHandle fh_barcode(BARCODE, htio2::READ);
+ string line;
+
+ while (fh_barcode.read_line(line))
+ {
+ size_t tab1 = line.find_first_of('\t');
+ if (tab1 == string::npos)
+ {
+ cerr << "line contain no TAB" << endl
+ << line << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ size_t tab2 = line.find_first_of('\t', tab1+1);
+ if (tab2 == string::npos)
+ {
+ cerr << "line contain no 2nd TAB" << endl
+ << line << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ string proj(line.substr(0, tab1));
+ string sample(line.substr(tab1 + 1, tab2 - tab1 - 1));
+ string barcode(line.substr(tab2 + 1));
+
+ barcodes.insert(make_pair(barcode, make_pair(proj, sample)));
+ }
+
+}
+
+void TestFramework::content()
+{
+ const char* cmd =
+ "../src/ht2-demul -q -P"
+ " -i " FILE1 " " FILE2
+ " --barcode " BARCODE
+ " -o demul";
+ ok(!system(cmd), cmd);
+
+ BarcodeMap barcodes;
+ read_barcode(barcodes);
+
+ File dir_out("demul");
+ size_t n_seq = 0;
+
+ // traverse projects
+ Array<File> dirs_project;
+ dir_out.findChildFiles(dirs_project, File::findDirectories, false);
+
+ htio2::FastqSeq seq;
+
+ for (int i_proj = 0; i_proj < dirs_project.size(); i_proj++)
+ {
+ const File& dir_proj = dirs_project[i_proj];
+ String proj_name = dir_proj.getFileName();
+
+ Array<File> seq_files;
+ dir_proj.findChildFiles(seq_files, File::findFiles, false);
+
+ for (int i_file = 0; i_file < seq_files.size(); i_file++)
+ {
+ const File& seq_file = seq_files[i_file];
+ String file_base = seq_file.getFileName();
+ int i_suffix = file_base.indexOf(".fastq");
+ String sample_name = file_base.substring(0, i_suffix-2);
+
+ // check the content of this file
+ htio2::FastqIO fh(seq_file.getFullPathName().toStdString(), htio2::READ);
+ while (fh.next_seq(seq))
+ {
+ n_seq++;
+ string barcode = seq.desc.substr(seq.desc.find_last_of(':')+1);
+ BarcodeMap::iterator it_barcode = barcodes.find(barcode);
+ ok(it_barcode != barcodes.end(), (barcode + " barcode exist").c_str());
+ const string& barcode_proj = it_barcode->second.first;
+ const string& barcode_sample = it_barcode->second.second;
+
+ IS(file_base[i_suffix-1], seq.desc[0]);
+ is(barcode_proj, proj_name.toStdString(), ("project " + barcode_proj + " is " + proj_name.toStdString()).c_str());
+ is(barcode_sample, sample_name.toStdString(), ("sample " + barcode_sample + " is " + sample_name.toStdString()).c_str());
+ }
+ }
+ }
+
+ // traverse demul failed files
+ Array<File> files_fail;
+ dir_out.findChildFiles(files_fail, File::findFiles, false, "demul_failed*.fastq.gz");
+ IS(files_fail.size(), 2);
+
+ for (int i_file = 0; i_file < files_fail.size(); i_file++)
+ {
+ htio2::FastqIO fh(files_fail[i_file].getFullPathName().toStdString(), htio2::READ);
+ while (fh.next_seq(seq))
+ {
+ n_seq++;
+ string barcode = seq.desc.substr(seq.desc.find_last_of(':')+1);
+ BarcodeMap::iterator it = barcodes.find(barcode);
+ ok(it == barcodes.end(), (barcode + " unknown").c_str());
+ }
+ }
+
+ IS(n_seq, 200);
+}
diff --git a/t/t_ht_filter.cpp b/t/t_ht_filter.cpp
new file mode 100644
index 0000000..49dee7e
--- /dev/null
+++ b/t/t_ht_filter.cpp
@@ -0,0 +1,101 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+
+#define BIN "../src/ht2-filter"
+#define FILE1 TEST_SOURCE_DIR "/test1.fastq.gz"
+#define FILE2 TEST_SOURCE_DIR "/test2.fastq.gz"
+
+#include "htio2/JUCE-3.0.8/JuceHeader.h"
+
+using namespace std;
+using namespace htio2::juce;
+
+size_t high_qual_len(const string& qual)
+{
+ size_t num = 0;
+
+ for (size_t i = 0; i < qual.length(); i++)
+ {
+ // 33-based, quality cutoff 30
+ if (qual[i] >= 33 + 30)
+ num++;
+ }
+
+ return num;
+}
+
+void TestFramework::content()
+{
+ // paired-end test
+ {
+ const char* cmd =
+ BIN
+ " -q -P"
+ " -Q 30 -L 120"
+ " -i " FILE1 " " FILE2
+ " -o filt"
+ " -u filt_fail";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/filt_1.fastq.gz", "filt_1.fastq.gz"));
+ OK(text_file_eq(TEST_SOURCE_DIR "/filt_2.fastq.gz", "filt_2.fastq.gz"));
+ OK(text_file_eq(TEST_SOURCE_DIR "/filt_s.fastq.gz", "filt_s.fastq.gz"));
+ // ID match
+ OK(seq_file_id_eq("filt_1.fastq.gz", "filt_2.fastq.gz"));
+ OK(seq_file_id_eq("filt_fail_1.fastq.gz", "filt_fail_2.fastq.gz"));
+ OK(seq_file_id_eq("filt_s.fastq.gz", "filt_fail_s.fastq.gz"));
+ }
+
+ {
+ const char* cmd =
+ BIN
+ " -q -S"
+ " -Q 30 -L 120"
+ " -i " TEST_SOURCE_DIR "/test_interleave.fastq.gz"
+ " -o filt -u filt_fail";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/filt.fastq.gz", "filt.fastq.gz"));
+ OK(text_file_eq(TEST_SOURCE_DIR "/filt_fail.fastq.gz", "filt_fail.fastq.gz"));
+ }
+
+ {
+ vector<string> files_accepted;
+ files_accepted.push_back("filt_1.fastq.gz");
+ files_accepted.push_back("filt_2.fastq.gz");
+ files_accepted.push_back("filt_s.fastq.gz");
+ files_accepted.push_back("filt.fastq.gz");
+
+ vector<string> files_rejected;
+ files_rejected.push_back("filt_fail_1.fastq.gz");
+ files_rejected.push_back("filt_fail_2.fastq.gz");
+ files_rejected.push_back("filt_fail_s.fastq.gz");
+ files_rejected.push_back("filt_fail.fastq.gz");
+
+ size_t num = 0;
+ htio2::FastqSeq seq;
+
+ for (size_t i = 0; i < files_accepted.size(); i++)
+ {
+ htio2::FastqIO fh(files_accepted[i], htio2::READ, htio2::COMPRESS_GZIP);
+ while (fh.next_seq(seq))
+ {
+ GE(high_qual_len(seq.quality), 120);
+ num++;
+ }
+ }
+
+ for (size_t i = 0; i < files_rejected.size(); i++)
+ {
+ htio2::FastqIO fh(files_rejected[i], htio2::READ, htio2::COMPRESS_GZIP);
+ while (fh.next_seq(seq))
+ {
+ LT(high_qual_len(seq.quality), 120);
+ num++;
+ }
+ }
+
+ is(num, 400, "400 sequences in total");
+ }
+}
diff --git a/t/t_ht_lane_tile.cpp b/t/t_ht_lane_tile.cpp
new file mode 100644
index 0000000..b45e372
--- /dev/null
+++ b/t/t_ht_lane_tile.cpp
@@ -0,0 +1,38 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+
+using namespace std;
+
+#define BIN "../src/ht2-lane-tile"
+#define INPUT TEST_SOURCE_DIR"/test_interleave.fastq.gz"
+
+size_t count_seq(const string& file)
+{
+ size_t result = 0;
+ htio2::FastqIO fh_accept(file, htio2::READ);
+ htio2::FastqSeq seq;
+ while (fh_accept.next_seq(seq))
+ result++;
+ return result;
+}
+
+void TestFramework::content()
+{
+ const char* cmd = BIN
+ " -q"
+ " -i " INPUT
+ " -o lane_tile"
+ " -u lane_tile_reject"
+ " -T 1101";
+
+ ok(!system(cmd), cmd);
+
+ size_t n_accept = count_seq("lane_tile.fastq.gz");
+ size_t n_reject = count_seq("lane_tile_reject.fastq.gz");
+
+ IS(n_accept, 0);
+ IS(n_reject, 200);
+}
diff --git a/t/t_ht_overlap.cpp b/t/t_ht_overlap.cpp
new file mode 100644
index 0000000..83a171c
--- /dev/null
+++ b/t/t_ht_overlap.cpp
@@ -0,0 +1,11 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+
+void TestFramework::content()
+{
+ const char* cmd = "../src/ht2-overlap -q -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz -o ovlp -u novlp";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq("ovlp.fastq.gz", TEST_SOURCE_DIR "/test_ovlp.fastq.gz"));
+ OK(text_file_eq("novlp_1.fastq.gz", TEST_SOURCE_DIR "/test_novlp_1.fastq.gz"));
+ OK(text_file_eq("novlp_2.fastq.gz", TEST_SOURCE_DIR "/test_novlp_2.fastq.gz"));
+}
diff --git a/t/t_ht_rename.cpp b/t/t_ht_rename.cpp
new file mode 100644
index 0000000..cf10afe
--- /dev/null
+++ b/t/t_ht_rename.cpp
@@ -0,0 +1,37 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htio2/FastqIO.h"
+#include "htio2/FastqSeq.h"
+
+void TestFramework::content()
+{
+ const char* cmd = "../src/ht2-rename --quiet -i " TEST_SOURCE_DIR "/test1.fastq.gz -o rename --prefix aaa_ --suffix _bbb";
+ ok(!system(cmd), cmd);
+
+ htio2::FastqIO fh("rename.fastq.gz", htio2::READ, htio2::COMPRESS_GZIP);
+ htio2::FastqSeq seq;
+
+ size_t n = 0;
+ while (fh.next_seq(seq))
+ {
+ n++;
+ if (n==1)
+ {
+ IS(seq.id, "aaa_1_bbb");
+ IS(seq.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq.quality, "=?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA?ABCAC at 9@AA8??8><ADB<>B8<B:C?>@>>34>:@CD");
+ }
+ else if (n==2)
+ {
+ IS(seq.id, "aaa_2_bbb");
+ IS(seq.seq, "AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTGGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATNNTGACGGTACCTGACTAAGAAGCTCCGGCTAACTA");
+ IS(seq.quality, "@@CFFDFFGHHHHJJHFHGHHGIIHIJJJJIHHJJJJGIGIJHIJGIICFC at ECEHAB@4=;@DBB8B at B:@:>C>>CCCD:?CDDDDBDEEEDCCDCDDCCCC@@ADD?BDBD##++8?@B9A9CDCCCCCDDCDCCD at C>BBDDCDDD");
+ }
+ else if (n==100)
+ {
+ IS(seq.id, "aaa_100_bbb");
+ IS(seq.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ }
+ }
+}
diff --git a/t/t_ht_sample.cpp b/t/t_ht_sample.cpp
new file mode 100644
index 0000000..1a8020d
--- /dev/null
+++ b/t/t_ht_sample.cpp
@@ -0,0 +1,81 @@
+#include "TestConfig.h"
+#include "TestFramework.h"
+
+#include "htio2/PairedEndIO.h"
+#include "htio2/PlainFileHandle.h"
+#include "htio2/Cast.h"
+
+#include <set>
+
+using namespace std;
+
+void read_idx(const string& file, vector<int64_t>& result)
+{
+ htio2::PlainFileHandle fh(file, htio2::READ);
+ string line;
+ while (fh.read_line(line))
+ {
+ int64_t idx;
+ if (!htio2::from_string<int64_t>(line, idx))
+ {
+ fprintf(stderr, "failed to parse line to integer: \"%s\"\n", line.c_str());
+ abort();
+ }
+ printf(" %ld\n", idx);
+ result.push_back(idx);
+ }
+}
+
+bool operator == (htio2::FastqSeq& seq1, htio2::FastqSeq& seq2)
+{
+ return seq1.id == seq2.id && seq1.desc == seq2.desc && seq1.seq == seq2.seq && seq1.quality == seq2.quality;
+}
+
+void TestFramework::content()
+{
+ const char* cmd = "../src/ht2-sample -P"
+ " -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz"
+ " -o sample"
+ " --out-id sample_id"
+ " --seed 3 --num 15";
+ ok(!system(cmd), cmd);
+
+ vector<int64_t> idx_used;
+ read_idx("sample_id", idx_used);
+ IS(idx_used.size(), 15);
+
+ htio2::PairedEndIO fh_input(TEST_SOURCE_DIR "/test1.fastq.gz",
+ TEST_SOURCE_DIR "/test2.fastq.gz",
+ htio2::READ,
+ htio2::STRAND_FWD,
+ htio2::STRAND_REV);
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+ vector<htio2::FastqSeq> seqs_1;
+ vector<htio2::FastqSeq> seqs_2;
+
+ while (fh_input.next_pair(seq1, seq2, htio2::STRAND_FWD, htio2::STRAND_REV))
+ {
+ seqs_1.push_back(seq1);
+ seqs_2.push_back(seq2);
+ }
+
+ htio2::PairedEndIO fh_result("sample_1.fastq.gz",
+ "sample_2.fastq.gz",
+ htio2::READ,
+ htio2::STRAND_FWD,
+ htio2::STRAND_REV);
+
+
+ size_t n = 0;
+ while (fh_result.next_pair(seq1, seq2, htio2::STRAND_FWD, htio2::STRAND_REV))
+ {
+ IS(seq1.desc[0], '1');
+ IS(seq2.desc[0], '2');
+ OK(seqs_1[idx_used[n]] == seq1);
+ OK(seqs_2[idx_used[n]] == seq2);
+ n++;
+ }
+
+}
diff --git a/t/t_ht_trim.cpp b/t/t_ht_trim.cpp
new file mode 100644
index 0000000..76821c4
--- /dev/null
+++ b/t/t_ht_trim.cpp
@@ -0,0 +1,24 @@
+#include "TestConfig.h"
+#include "TestFramework.h"
+
+void TestFramework::content()
+{
+ {
+ const char* cmd = "../src/ht2-trim --quiet -i " TEST_SOURCE_DIR "/test1.fastq.gz -S head -o trim_head";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/trim_head.fastq.gz", "trim_head.fastq.gz"));
+ }
+
+ {
+ const char* cmd = "../src/ht2-trim --quiet -i " TEST_SOURCE_DIR "/test1.fastq.gz -S tail -o trim_tail";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/trim_tail.fastq.gz", "trim_tail.fastq.gz"));
+ }
+
+ {
+ const char* cmd = "../src/ht2-trim --quiet -i " TEST_SOURCE_DIR "/test1.fastq.gz -o trim_both";
+ ok(!system(cmd), cmd);
+ OK(text_file_eq(TEST_SOURCE_DIR "/trim_both.fastq.gz", "trim_both.fastq.gz"));
+ }
+}
+
diff --git a/t/t_kmer_aa.cpp b/t/t_kmer_aa.cpp
new file mode 100644
index 0000000..a3e57cf
--- /dev/null
+++ b/t/t_kmer_aa.cpp
@@ -0,0 +1,60 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+using namespace htio2;
+using namespace std;
+
+void TestFramework::content()
+{
+ for (char c = 'A'; c <= 'Z'; c++)
+ {
+ cout << "encode " << c << endl;
+ IS(encode_aa(c), EncodedType(c-'A'));
+ }
+
+ for (EncodedType enc = 0; enc <= 25; enc++)
+ {
+ cout << "decode " << int(enc) << endl;
+ IS(decode_aa(enc), 'A'+enc=='O' ? '*' : char('A'+enc));
+ }
+
+ {
+ uint64_t manual_kmer =
+ ('A'-'A') +
+ ('F'-'A') * 26 +
+ ('O'-'A') * 26 * 26 +
+ ('C'-'A') * 26 * 26 * 26 +
+ ('Z'-'A') * 26 * 26 * 26 * 26;
+ IS(gen_kmer_aa<uint64_t>("AF*CZ"), manual_kmer);
+ }
+
+ {
+ EncodedSeq enc;
+ encode_aa("AF*KZ", enc);
+ IS(enc.size(), size_t(5));
+ IS(enc[0], EncodedType('A'-'A'));
+ IS(enc[1], EncodedType('F'-'A'));
+ IS(enc[2], EncodedType('O'-'A'));
+ IS(enc[3], EncodedType('K'-'A'));
+ IS(enc[4], EncodedType('Z'-'A'));
+
+ vector<uint16_t> kmers;
+ gen_kmer_aa(enc, kmers, 3);
+ IS(kmers.size(), size_t(3));
+ IS(kmers[0], uint16_t( ('A'-'A') + ('F'-'A')*26 + ('O'-'A')*26*26 ));
+ IS(kmers[1], uint16_t( ('F'-'A') + ('O'-'A')*26 + ('K'-'A')*26*26 ));
+ IS(kmers[2], uint16_t( ('O'-'A') + ('K'-'A')*26 + ('Z'-'A')*26*26 ));
+
+
+ string dec;
+ decode_aa(enc, dec);
+ IS(dec, string("AF*KZ"));
+
+ encode_aa("*", enc);
+ IS(enc.size(), size_t(1));
+ IS(enc[0], EncodedType('O'-'A'));
+
+ decode_aa(enc, dec);
+ IS(dec, string("*"));
+ }
+}
diff --git a/t/t_kmer_nt4_16.cpp b/t/t_kmer_nt4_16.cpp
new file mode 100644
index 0000000..62974b1
--- /dev/null
+++ b/t/t_kmer_nt4_16.cpp
@@ -0,0 +1,96 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint16_t KmerType;
+
+void TestFramework::content()
+{
+ IS(ENCODED_NT4_A, 0);
+ IS(ENCODED_NT4_T, 3);
+ IS(ENCODED_NT4_G, 1);
+ IS(ENCODED_NT4_C, 2);
+
+ IS(encode_nt4('N'), ENCODED_ERROR);
+ IS(encode_nt4('A'), ENCODED_NT4_A);
+ IS(encode_nt4('T'), ENCODED_NT4_T);
+ IS(encode_nt4('G'), ENCODED_NT4_G);
+ IS(encode_nt4('C'), ENCODED_NT4_C);
+ IS(encode_nt4('Z'), ENCODED_ERROR);
+ IS(encode_nt4('B'), ENCODED_ERROR);
+
+ IS(decode_nt4(ENCODED_ERROR), 'N');
+ IS(decode_nt4(ENCODED_NT4_A), 'A');
+ IS(decode_nt4(ENCODED_NT4_T), 'T');
+ IS(decode_nt4(ENCODED_NT4_G), 'G');
+ IS(decode_nt4(ENCODED_NT4_C), 'C');
+
+ // encode
+ EncodedSeq enc;
+ encode_nt4("ATGXCATA", enc);
+ IS(enc.size(), 8);
+ IS(enc[0], ENCODED_NT4_A);
+ IS(enc[1], ENCODED_NT4_T);
+ IS(enc[2], ENCODED_NT4_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT4_C);
+ IS(enc[5], ENCODED_NT4_A);
+ IS(enc[6], ENCODED_NT4_T);
+ IS(enc[7], ENCODED_NT4_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 3));
+ IS(kmers.size(), 6);
+ IS(kmers[0], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[5], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+
+ // decode kmer
+ IS(decode_kmer_nt4(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[1], 3), "");
+ IS(decode_kmer_nt4(kmers[2], 3), "");
+ IS(decode_kmer_nt4(kmers[3], 3), "");
+ IS(decode_kmer_nt4(kmers[4], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[5], 3), "ATA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 7));
+ IS(kmers.size(), 2);
+
+ KmerType kmer =
+ ENCODED_NT4_A +
+ ENCODED_NT4_T *4 +
+ ENCODED_NT4_G *4*4 +
+ ENCODED_NT4_C *4*4*4 +
+ ENCODED_NT4_A *4*4*4*4 +
+ ENCODED_NT4_T *4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4;
+ IS(gen_kmer_nt4<KmerType>("ATGCATA"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt4(enc, kmers, 8));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt4<KmerType>("ATGCATAA"), numeric_limits<KmerType>::max());
+ }
+
+ // decode
+ {
+ string dec;
+ decode_nt4(enc, dec);
+ IS(dec, "ATGNCATA");
+ }
+}
diff --git a/t/t_kmer_nt4_32.cpp b/t/t_kmer_nt4_32.cpp
new file mode 100644
index 0000000..db90c01
--- /dev/null
+++ b/t/t_kmer_nt4_32.cpp
@@ -0,0 +1,109 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint32_t KmerType;
+
+void TestFramework::content()
+{
+ // encode
+ EncodedSeq enc;
+ encode_nt4("ATGXCATAATGXCATA", enc);
+ IS(enc.size(), 16);
+ IS(enc[0], ENCODED_NT4_A);
+ IS(enc[1], ENCODED_NT4_T);
+ IS(enc[2], ENCODED_NT4_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT4_C);
+ IS(enc[5], ENCODED_NT4_A);
+ IS(enc[6], ENCODED_NT4_T);
+ IS(enc[7], ENCODED_NT4_A);
+ IS(enc[8], ENCODED_NT4_A);
+ IS(enc[9], ENCODED_NT4_T);
+ IS(enc[10], ENCODED_NT4_G);
+ IS(enc[11], ENCODED_ERROR);
+ IS(enc[12], ENCODED_NT4_C);
+ IS(enc[13], ENCODED_NT4_A);
+ IS(enc[14], ENCODED_NT4_T);
+ IS(enc[15], ENCODED_NT4_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 3));
+ IS(kmers.size(), 14);
+ IS(kmers[0], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[5], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[6], ENCODED_NT4_T + ENCODED_NT4_A*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[7], ENCODED_NT4_A + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[8], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[9], numeric_limits<KmerType>::max());
+ IS(kmers[10], numeric_limits<KmerType>::max());
+ IS(kmers[11], numeric_limits<KmerType>::max());
+ IS(kmers[12], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[13], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+
+ // decode kmer
+ IS(decode_kmer_nt4(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[1], 3), "");
+ IS(decode_kmer_nt4(kmers[2], 3), "");
+ IS(decode_kmer_nt4(kmers[3], 3), "");
+ IS(decode_kmer_nt4(kmers[4], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[5], 3), "ATA");
+ IS(decode_kmer_nt4(kmers[6], 3), "TAA");
+ IS(decode_kmer_nt4(kmers[7], 3), "AAT");
+ IS(decode_kmer_nt4(kmers[8], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[9], 3), "");
+ IS(decode_kmer_nt4(kmers[10], 3), "");
+ IS(decode_kmer_nt4(kmers[11], 3), "");
+ IS(decode_kmer_nt4(kmers[12], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[13], 3), "ATA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 15));
+ IS(kmers.size(), 2);
+
+ KmerType kmer =
+ ENCODED_NT4_A +
+ ENCODED_NT4_T *4 +
+ ENCODED_NT4_G *4*4 +
+ ENCODED_NT4_C *4*4*4 +
+ ENCODED_NT4_A *4*4*4*4 +
+ ENCODED_NT4_T *4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4*4 +
+ ENCODED_NT4_T *4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_G *4*4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_C *4*4*4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_T *4*4*4*4*4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4*4*4*4*4*4*4*4 +
+ ENCODED_NT4_A *4*4*4*4*4*4*4*4*4*4*4*4*4*4;
+ IS(gen_kmer_nt4<KmerType>("ATGCATAATGCATAA"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt4(enc, kmers, 16));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt4<KmerType>("ATGCATAATGCATAAA"), numeric_limits<KmerType>::max());
+ }
+
+ // decode
+ {
+ string dec;
+ decode_nt4(enc, dec);
+ IS(dec, "ATGNCATAATGNCATA");
+ }
+}
diff --git a/t/t_kmer_nt4_64.cpp b/t/t_kmer_nt4_64.cpp
new file mode 100644
index 0000000..8f31773
--- /dev/null
+++ b/t/t_kmer_nt4_64.cpp
@@ -0,0 +1,173 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint64_t KmerType;
+
+void TestFramework::content()
+{
+ // encode
+ EncodedSeq enc;
+ encode_nt4("ATGXCATAATGXCATAATGXCATAATGXCATA", enc);
+ IS(enc.size(), 32);
+ IS(enc[0], ENCODED_NT4_A);
+ IS(enc[1], ENCODED_NT4_T);
+ IS(enc[2], ENCODED_NT4_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT4_C);
+ IS(enc[5], ENCODED_NT4_A);
+ IS(enc[6], ENCODED_NT4_T);
+ IS(enc[7], ENCODED_NT4_A);
+ IS(enc[8], ENCODED_NT4_A);
+ IS(enc[9], ENCODED_NT4_T);
+ IS(enc[10], ENCODED_NT4_G);
+ IS(enc[11], ENCODED_ERROR);
+ IS(enc[12], ENCODED_NT4_C);
+ IS(enc[13], ENCODED_NT4_A);
+ IS(enc[14], ENCODED_NT4_T);
+ IS(enc[15], ENCODED_NT4_A);
+ IS(enc[16], ENCODED_NT4_A);
+ IS(enc[17], ENCODED_NT4_T);
+ IS(enc[18], ENCODED_NT4_G);
+ IS(enc[19], ENCODED_ERROR);
+ IS(enc[20], ENCODED_NT4_C);
+ IS(enc[21], ENCODED_NT4_A);
+ IS(enc[22], ENCODED_NT4_T);
+ IS(enc[23], ENCODED_NT4_A);
+ IS(enc[24], ENCODED_NT4_A);
+ IS(enc[25], ENCODED_NT4_T);
+ IS(enc[26], ENCODED_NT4_G);
+ IS(enc[27], ENCODED_ERROR);
+ IS(enc[28], ENCODED_NT4_C);
+ IS(enc[29], ENCODED_NT4_A);
+ IS(enc[30], ENCODED_NT4_T);
+ IS(enc[31], ENCODED_NT4_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 3));
+ IS(kmers.size(), 30);
+ IS(kmers[0], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[5], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[6], ENCODED_NT4_T + ENCODED_NT4_A*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[7], ENCODED_NT4_A + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[8], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[9], numeric_limits<KmerType>::max());
+ IS(kmers[10], numeric_limits<KmerType>::max());
+ IS(kmers[11], numeric_limits<KmerType>::max());
+ IS(kmers[12], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[13], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[14], ENCODED_NT4_T + ENCODED_NT4_A*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[15], ENCODED_NT4_A + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[16], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[17], numeric_limits<KmerType>::max());
+ IS(kmers[18], numeric_limits<KmerType>::max());
+ IS(kmers[19], numeric_limits<KmerType>::max());
+ IS(kmers[20], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[21], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[22], ENCODED_NT4_T + ENCODED_NT4_A*4 + ENCODED_NT4_A*4*4);
+ IS(kmers[23], ENCODED_NT4_A + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[24], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_G*4*4);
+ IS(kmers[25], numeric_limits<KmerType>::max());
+ IS(kmers[26], numeric_limits<KmerType>::max());
+ IS(kmers[27], numeric_limits<KmerType>::max());
+ IS(kmers[28], ENCODED_NT4_C + ENCODED_NT4_A*4 + ENCODED_NT4_T*4*4);
+ IS(kmers[29], ENCODED_NT4_A + ENCODED_NT4_T*4 + ENCODED_NT4_A*4*4);
+
+ // decode kmer
+ IS(decode_kmer_nt4(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[1], 3), "");
+ IS(decode_kmer_nt4(kmers[2], 3), "");
+ IS(decode_kmer_nt4(kmers[3], 3), "");
+ IS(decode_kmer_nt4(kmers[4], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[5], 3), "ATA");
+ IS(decode_kmer_nt4(kmers[6], 3), "TAA");
+ IS(decode_kmer_nt4(kmers[7], 3), "AAT");
+ IS(decode_kmer_nt4(kmers[8], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[9], 3), "");
+ IS(decode_kmer_nt4(kmers[10], 3), "");
+ IS(decode_kmer_nt4(kmers[11], 3), "");
+ IS(decode_kmer_nt4(kmers[12], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[13], 3), "ATA");
+ IS(decode_kmer_nt4(kmers[14], 3), "TAA");
+ IS(decode_kmer_nt4(kmers[15], 3), "AAT");
+ IS(decode_kmer_nt4(kmers[16], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[17], 3), "");
+ IS(decode_kmer_nt4(kmers[18], 3), "");
+ IS(decode_kmer_nt4(kmers[19], 3), "");
+ IS(decode_kmer_nt4(kmers[20], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[21], 3), "ATA");
+ IS(decode_kmer_nt4(kmers[22], 3), "TAA");
+ IS(decode_kmer_nt4(kmers[23], 3), "AAT");
+ IS(decode_kmer_nt4(kmers[24], 3), "ATG");
+ IS(decode_kmer_nt4(kmers[25], 3), "");
+ IS(decode_kmer_nt4(kmers[26], 3), "");
+ IS(decode_kmer_nt4(kmers[27], 3), "");
+ IS(decode_kmer_nt4(kmers[28], 3), "CAT");
+ IS(decode_kmer_nt4(kmers[29], 3), "ATA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt4(enc, kmers, 31));
+ IS(kmers.size(), 2);
+
+ KmerType kmer =
+ ENCODED_NT4_A +
+ ENCODED_NT4_T *4L +
+ ENCODED_NT4_G *4L*4L +
+ ENCODED_NT4_C *4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_G *4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_C *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_G *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_C *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_G *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_C *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_T *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L +
+ ENCODED_NT4_A *4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L*4L;
+ IS(gen_kmer_nt4<KmerType>("ATGCATAATGCATAAATGCATAATGCATAAA"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt4(enc, kmers, 32));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt4<KmerType>("ATGCATAATGCATAAAATGCATAATGCATAAA"), numeric_limits<KmerType>::max());
+ }
+
+ // decode
+ {
+ string dec;
+ decode_nt4(enc, dec);
+ IS(dec, "ATGNCATAATGNCATAATGNCATAATGNCATA");
+ }
+}
diff --git a/t/t_kmer_nt5_16.cpp b/t/t_kmer_nt5_16.cpp
new file mode 100644
index 0000000..6457f6c
--- /dev/null
+++ b/t/t_kmer_nt5_16.cpp
@@ -0,0 +1,96 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint16_t KmerType;
+
+void TestFramework::content()
+{
+ IS(ENCODED_NT5_A, 0);
+ IS(ENCODED_NT5_T, 4);
+ IS(ENCODED_NT5_G, 1);
+ IS(ENCODED_NT5_C, 3);
+ IS(ENCODED_NT5_N, 2);
+
+ IS(encode_nt5('N'), ENCODED_NT5_N);
+ IS(encode_nt5('A'), ENCODED_NT5_A);
+ IS(encode_nt5('T'), ENCODED_NT5_T);
+ IS(encode_nt5('G'), ENCODED_NT5_G);
+ IS(encode_nt5('C'), ENCODED_NT5_C);
+ IS(encode_nt5('Z'), ENCODED_ERROR);
+ IS(encode_nt5('B'), ENCODED_ERROR);
+
+ IS(decode_nt5(ENCODED_NT5_N), 'N');
+ IS(decode_nt5(ENCODED_NT5_A), 'A');
+ IS(decode_nt5(ENCODED_NT5_T), 'T');
+ IS(decode_nt5(ENCODED_NT5_G), 'G');
+ IS(decode_nt5(ENCODED_NT5_C), 'C');
+
+ // encode
+ EncodedSeq enc;
+ encode_nt5("ATGXCNTA", enc);
+ IS(enc.size(), 8);
+ IS(enc[0], ENCODED_NT5_A);
+ IS(enc[1], ENCODED_NT5_T);
+ IS(enc[2], ENCODED_NT5_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT5_C);
+ IS(enc[5], ENCODED_NT5_N);
+ IS(enc[6], ENCODED_NT5_T);
+ IS(enc[7], ENCODED_NT5_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 3));
+ IS(kmers.size(), 6);
+ IS(kmers[0], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[5], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+
+ // decode kmer
+ IS(decode_kmer_nt5(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[1], 3), "");
+ IS(decode_kmer_nt5(kmers[2], 3), "");
+ IS(decode_kmer_nt5(kmers[3], 3), "");
+ IS(decode_kmer_nt5(kmers[4], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[5], 3), "NTA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 6));
+ IS(kmers.size(), 3);
+
+ KmerType kmer =
+ ENCODED_NT5_A +
+ ENCODED_NT5_T *5 +
+ ENCODED_NT5_G *5*5 +
+ ENCODED_NT5_C *5*5*5 +
+ ENCODED_NT5_N *5*5*5*5 +
+ ENCODED_NT5_T *5*5*5*5*5 ;
+ IS(gen_kmer_nt5<KmerType>("ATGCNT"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt5(enc, kmers, 7));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt5<KmerType>("ATGCNTT"), numeric_limits<KmerType>::max());
+ }
+
+ // decode
+ {
+ string dec;
+ decode_nt5(enc, dec);
+ IS(dec, "ATGNCNTA");
+ }
+}
diff --git a/t/t_kmer_nt5_32.cpp b/t/t_kmer_nt5_32.cpp
new file mode 100644
index 0000000..4cd0cde
--- /dev/null
+++ b/t/t_kmer_nt5_32.cpp
@@ -0,0 +1,100 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint32_t KmerType;
+
+void TestFramework::content()
+{
+ // encode
+ EncodedSeq enc;
+ encode_nt5("ATGXCNTAATGXCNTA", enc);
+ IS(enc.size(), 16);
+ IS(enc[0], ENCODED_NT5_A);
+ IS(enc[1], ENCODED_NT5_T);
+ IS(enc[2], ENCODED_NT5_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT5_C);
+ IS(enc[5], ENCODED_NT5_N);
+ IS(enc[6], ENCODED_NT5_T);
+ IS(enc[7], ENCODED_NT5_A);
+ IS(enc[8], ENCODED_NT5_A);
+ IS(enc[9], ENCODED_NT5_T);
+ IS(enc[10], ENCODED_NT5_G);
+ IS(enc[11], ENCODED_ERROR);
+ IS(enc[12], ENCODED_NT5_C);
+ IS(enc[13], ENCODED_NT5_N);
+ IS(enc[14], ENCODED_NT5_T);
+ IS(enc[15], ENCODED_NT5_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 3));
+ IS(kmers.size(), 14);
+ IS(kmers[0], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[5], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[6], ENCODED_NT5_T + ENCODED_NT5_A*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[7], ENCODED_NT5_A + ENCODED_NT5_A*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[8], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[9], numeric_limits<KmerType>::max());
+ IS(kmers[10], numeric_limits<KmerType>::max());
+ IS(kmers[11], numeric_limits<KmerType>::max());
+ IS(kmers[12], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[13], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+
+ // decode kmer
+ IS(decode_kmer_nt5(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[1], 3), "");
+ IS(decode_kmer_nt5(kmers[2], 3), "");
+ IS(decode_kmer_nt5(kmers[3], 3), "");
+ IS(decode_kmer_nt5(kmers[4], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[5], 3), "NTA");
+ IS(decode_kmer_nt5(kmers[6], 3), "TAA");
+ IS(decode_kmer_nt5(kmers[7], 3), "AAT");
+ IS(decode_kmer_nt5(kmers[8], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[9], 3), "");
+ IS(decode_kmer_nt5(kmers[10], 3), "");
+ IS(decode_kmer_nt5(kmers[11], 3), "");
+ IS(decode_kmer_nt5(kmers[12], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[13], 3), "NTA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 13));
+ IS(kmers.size(), 4);
+
+ KmerType kmer =
+ ENCODED_NT5_A +
+ ENCODED_NT5_T *5 +
+ ENCODED_NT5_G *5*5 +
+ ENCODED_NT5_C *5*5*5 +
+ ENCODED_NT5_N *5*5*5*5 +
+ ENCODED_NT5_T *5*5*5*5*5 +
+ ENCODED_NT5_A *5*5*5*5*5*5 +
+ ENCODED_NT5_T *5*5*5*5*5*5*5 +
+ ENCODED_NT5_G *5*5*5*5*5*5*5*5 +
+ ENCODED_NT5_C *5*5*5*5*5*5*5*5*5 +
+ ENCODED_NT5_N *5*5*5*5*5*5*5*5*5*5 +
+ ENCODED_NT5_T *5*5*5*5*5*5*5*5*5*5*5 +
+ ENCODED_NT5_A *5*5*5*5*5*5*5*5*5*5*5*5;
+ IS(gen_kmer_nt5<KmerType>("ATGCNTATGCNTA"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt5(enc, kmers, 14));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt5<KmerType>("ATGCNTTATGCNTT"), numeric_limits<KmerType>::max());
+ }
+}
diff --git a/t/t_kmer_nt5_64.cpp b/t/t_kmer_nt5_64.cpp
new file mode 100644
index 0000000..3815171
--- /dev/null
+++ b/t/t_kmer_nt5_64.cpp
@@ -0,0 +1,162 @@
+#include "TestFramework.h"
+#include "htio2/Kmer.h"
+
+#include <limits>
+
+using namespace htio2;
+using namespace std;
+
+typedef uint64_t KmerType;
+
+void TestFramework::content()
+{
+ // encode
+ EncodedSeq enc;
+ encode_nt5("ATGXCNTAATGXCNTAATGXCNTAATGXCNTAATGXCNTAATGXCNTAATGXCNTAATGXCNTA", enc);
+ IS(enc.size(), 64);
+ IS(enc[0], ENCODED_NT5_A);
+ IS(enc[1], ENCODED_NT5_T);
+ IS(enc[2], ENCODED_NT5_G);
+ IS(enc[3], ENCODED_ERROR);
+ IS(enc[4], ENCODED_NT5_C);
+ IS(enc[5], ENCODED_NT5_N);
+ IS(enc[6], ENCODED_NT5_T);
+ IS(enc[7], ENCODED_NT5_A);
+ IS(enc[8], ENCODED_NT5_A);
+ IS(enc[9], ENCODED_NT5_T);
+ IS(enc[10], ENCODED_NT5_G);
+ IS(enc[11], ENCODED_ERROR);
+ IS(enc[12], ENCODED_NT5_C);
+ IS(enc[13], ENCODED_NT5_N);
+ IS(enc[14], ENCODED_NT5_T);
+ IS(enc[15], ENCODED_NT5_A);
+ IS(enc[16], ENCODED_NT5_A);
+ IS(enc[17], ENCODED_NT5_T);
+ IS(enc[18], ENCODED_NT5_G);
+ IS(enc[19], ENCODED_ERROR);
+ IS(enc[20], ENCODED_NT5_C);
+ IS(enc[21], ENCODED_NT5_N);
+ IS(enc[22], ENCODED_NT5_T);
+ IS(enc[23], ENCODED_NT5_A);
+ IS(enc[24], ENCODED_NT5_A);
+ IS(enc[25], ENCODED_NT5_T);
+ IS(enc[26], ENCODED_NT5_G);
+ IS(enc[27], ENCODED_ERROR);
+ IS(enc[28], ENCODED_NT5_C);
+ IS(enc[29], ENCODED_NT5_N);
+ IS(enc[30], ENCODED_NT5_T);
+ IS(enc[31], ENCODED_NT5_A);
+
+ {
+ // generate kmer
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 3));
+ IS(kmers.size(), 62);
+ IS(kmers[0], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[1], numeric_limits<KmerType>::max());
+ IS(kmers[2], numeric_limits<KmerType>::max());
+ IS(kmers[3], numeric_limits<KmerType>::max());
+ IS(kmers[4], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[5], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[6], ENCODED_NT5_T + ENCODED_NT5_A*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[7], ENCODED_NT5_A + ENCODED_NT5_A*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[8], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[9], numeric_limits<KmerType>::max());
+ IS(kmers[10], numeric_limits<KmerType>::max());
+ IS(kmers[11], numeric_limits<KmerType>::max());
+ IS(kmers[12], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[13], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[14], ENCODED_NT5_T + ENCODED_NT5_A*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[15], ENCODED_NT5_A + ENCODED_NT5_A*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[16], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[17], numeric_limits<KmerType>::max());
+ IS(kmers[18], numeric_limits<KmerType>::max());
+ IS(kmers[19], numeric_limits<KmerType>::max());
+ IS(kmers[20], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[21], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[22], ENCODED_NT5_T + ENCODED_NT5_A*5 + ENCODED_NT5_A*5*5);
+ IS(kmers[23], ENCODED_NT5_A + ENCODED_NT5_A*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[24], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
+ IS(kmers[25], numeric_limits<KmerType>::max());
+ IS(kmers[26], numeric_limits<KmerType>::max());
+ IS(kmers[27], numeric_limits<KmerType>::max());
+ IS(kmers[28], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
+ IS(kmers[29], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);
+
+ // decode kmer
+ IS(decode_kmer_nt5(kmers[0], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[1], 3), "");
+ IS(decode_kmer_nt5(kmers[2], 3), "");
+ IS(decode_kmer_nt5(kmers[3], 3), "");
+ IS(decode_kmer_nt5(kmers[4], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[5], 3), "NTA");
+ IS(decode_kmer_nt5(kmers[6], 3), "TAA");
+ IS(decode_kmer_nt5(kmers[7], 3), "AAT");
+ IS(decode_kmer_nt5(kmers[8], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[9], 3), "");
+ IS(decode_kmer_nt5(kmers[10], 3), "");
+ IS(decode_kmer_nt5(kmers[11], 3), "");
+ IS(decode_kmer_nt5(kmers[12], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[13], 3), "NTA");
+ IS(decode_kmer_nt5(kmers[14], 3), "TAA");
+ IS(decode_kmer_nt5(kmers[15], 3), "AAT");
+ IS(decode_kmer_nt5(kmers[16], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[17], 3), "");
+ IS(decode_kmer_nt5(kmers[18], 3), "");
+ IS(decode_kmer_nt5(kmers[19], 3), "");
+ IS(decode_kmer_nt5(kmers[20], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[21], 3), "NTA");
+ IS(decode_kmer_nt5(kmers[22], 3), "TAA");
+ IS(decode_kmer_nt5(kmers[23], 3), "AAT");
+ IS(decode_kmer_nt5(kmers[24], 3), "ATG");
+ IS(decode_kmer_nt5(kmers[25], 3), "");
+ IS(decode_kmer_nt5(kmers[26], 3), "");
+ IS(decode_kmer_nt5(kmers[27], 3), "");
+ IS(decode_kmer_nt5(kmers[28], 3), "CNT");
+ IS(decode_kmer_nt5(kmers[29], 3), "NTA");
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(gen_kmer_nt5(enc, kmers, 27));
+ IS(kmers.size(), 38);
+
+ KmerType kmer =
+ KmerType(ENCODED_NT5_A) +
+ KmerType(ENCODED_NT5_T *5L) +
+ KmerType(ENCODED_NT5_G *5L*5L) +
+ KmerType(ENCODED_NT5_C *5L*5L*5L) +
+ KmerType(ENCODED_NT5_N *5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_G *5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_C *5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_N *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_G *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_C *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_N *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_G *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_C *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_N *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_T *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L) +
+ KmerType(ENCODED_NT5_A *5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L*5L);
+ IS(gen_kmer_nt5<KmerType>("ATGCNTATGCNTAATGCNTATGCNTAA"), kmer);
+ }
+
+ {
+ vector<KmerType> kmers;
+ OK(!gen_kmer_nt5(enc, kmers, 28));
+ IS(kmers.size(), 0);
+
+ IS(gen_kmer_nt5<KmerType>("ATGCNTATGCNTAATGCNTATGCNTAAA"), numeric_limits<KmerType>::max());
+ }
+}
diff --git a/t/t_mt19937.cpp b/t/t_mt19937.cpp
new file mode 100644
index 0000000..112c53d
--- /dev/null
+++ b/t/t_mt19937.cpp
@@ -0,0 +1,167 @@
+#include "htio2/MT19937.h"
+#include "TestFramework.h"
+
+#include <vector>
+#include <cstring>
+
+using namespace htio2::juce;
+
+//
+// the reference implementation of 64-bit MT19937 by Takuji Nishimura and Makoto Matsumoto.
+// Copyright (C) 2004, 2014, Makoto Matsumoto and Takuji Nishimura, All rights reserved.
+//
+
+#define NN 312
+#define MM 156
+#define MATRIX_A 0xB5026F5AA96619E9ull
+#define UM 0xFFFFFFFF80000000ull
+#define LM 0x7FFFFFFFull
+
+static uint64_t mt[NN];
+static int mti=NN+1;
+
+void init_genrand64(uint64_t seed)
+{
+ mt[0] = seed;
+ for (mti=1; mti<NN; mti++)
+ mt[mti] = (6364136223846793005ull * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
+}
+
+void init_by_array64(uint64_t init_key[],
+ uint64_t key_length)
+{
+ unsigned int i, j;
+ uint64_t k;
+ init_genrand64(19650218ull);
+ i=1; j=0;
+ k = (NN>key_length ? NN : key_length);
+ for (; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ull))
+ + init_key[j] + j; /* non linear */
+ i++; j++;
+ if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
+ if (j>=key_length) j=0;
+ }
+ for (k=NN-1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ull))
+ - i; /* non linear */
+ i++;
+ if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
+ }
+
+ mt[0] = 1ull << 63; /* MSB is 1; assuring non-zero initial array */
+}
+
+uint64_t genrand64_int64(void)
+{
+ int i;
+ uint64_t x;
+ static uint64_t mag01[2]={0ull, MATRIX_A};
+
+ if (mti >= NN) { /* generate NN words at one time */
+
+ /* if init_genrand64() has not been called, */
+ /* a default initial seed is used */
+ if (mti == NN+1)
+ init_genrand64(5489ull);
+
+ for (i=0;i<NN-MM;i++) {
+ x = (mt[i]&UM)|(mt[i+1]&LM);
+ mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x & 1ull)];
+ }
+ for (;i<NN-1;i++) {
+ x = (mt[i]&UM)|(mt[i+1]&LM);
+ mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x & 1ull)];
+ }
+ x = (mt[NN-1]&UM)|(mt[0]&LM);
+ mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x & 1ull)];
+
+ mti = 0;
+ }
+
+ x = mt[mti++];
+
+ x ^= (x >> 29) & 0x5555555555555555ull;
+ x ^= (x << 17) & 0x71D67FFFEDA60000ull;
+ x ^= (x << 37) & 0xFFF7EEE000000000ull;
+ x ^= (x >> 43);
+
+ return x;
+}
+
+int64_t genrand64_int63(void)
+{
+ return (int64_t)(genrand64_int64() >> 1);
+}
+
+double genrand64_real1(void)
+{
+ return (genrand64_int64() >> 11) * (1.0/9007199254740991.0);
+}
+
+double genrand64_real2(void)
+{
+ return (genrand64_int64() >> 11) * (1.0/9007199254740992.0);
+}
+
+double genrand64_real3(void)
+{
+ return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0);
+}
+
+
+void TestFramework::content()
+{
+ uint64_t seed = Time::getCurrentTime().toMilliseconds();
+ printf("seed: %lu\n", seed);
+
+ htio2::MT19937 prng(seed);
+ init_genrand64(seed);
+
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+ is(genrand64_int64(), prng.next_uint64(), "uint64");
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+ is(genrand64_int63(), prng.next_int63(), "positive int64");
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+ is(genrand64_real1(), prng.next_double_yy(), "double inclusive");
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+ is(genrand64_real2(), prng.next_double_yn(), "double right exclusive");
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+ is(genrand64_real3(), prng.next_double_nn(), "double both exclusive");
+ OK(std::memcmp(mt, prng.mt, sizeof(mt)) == 0);
+ IS(mti, prng.mti);
+
+#define NUM_CYCLE 1000000
+ {
+ int32_t sum = 0;
+ for (int32_t i = 0; i < NUM_CYCLE; i++)
+ {
+ sum += prng.next_bool();
+ }
+
+ printf("%d of %d\n", sum, NUM_CYCLE);
+ }
+
+ {
+ std::vector<size_t> sum(10);
+ for (size_t i = 0; i < NUM_CYCLE; i++)
+ {
+ sum[prng.next_uint64_in_range(10)]++;
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ printf("%lu\n", sum[i]);
+ }
+ }
+}
diff --git a/t/t_multi_seq_file_pe.cpp b/t/t_multi_seq_file_pe.cpp
new file mode 100644
index 0000000..a2968b2
--- /dev/null
+++ b/t/t_multi_seq_file_pe.cpp
@@ -0,0 +1,141 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htqc/MultiSeqFile.h"
+
+using namespace std;
+
+void TestFramework::content()
+{
+ {
+ OK("test file pairs");
+ vector<string> files1;
+ files1.push_back(TEST_SOURCE_DIR"/test1.fastq.gz");
+ files1.push_back(TEST_SOURCE_DIR"/test1.fastq.gz");
+ vector<string> files2;
+ files2.push_back(TEST_SOURCE_DIR"/test2.fastq.gz");
+ files2.push_back(TEST_SOURCE_DIR"/test2.fastq.gz");
+
+ htqc::MultiSeqFilePE fh(files1, files2, htio2::STRAND_FWD, htio2::STRAND_REV, htio2::COMPRESS_GZIP);
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ size_t count = 0;
+
+ while (fh.next_pair(seq1, seq2, htio2::STRAND_FWD, htio2::STRAND_REV))
+ {
+ count++;
+ if (count == 1)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq1.quality, "=\?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3\?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA\?ABCAC at 9@AA8\?\?8><ADB<>B8<B:C\?>@>>34>:@CD");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq2.desc, "2:N:0:CTTGTA");
+ IS(seq2.seq, "CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC");
+ IS(seq2.quality, "=+=+<\?7@\?C0CACAABABABBAA=:<AABBBAAAAABBAABBBBAAAAA;\?@>>75>>=@>\?======;9;=8255+88=:\?\?\?\?\?\?\?\?\?=::=;<\?8883::8;8;;=;<=\?\?7<\?\?\?\?3;\?\?\?\?\?8;===\?\?\?\?\?\?###########");
+ }
+ else if (count==100)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq1.desc, "1:N:0:TTAGGC");
+ IS(seq2.desc, "2:N:0:TTAGGC");
+ IS(seq1.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq2.seq, "ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATGCATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCACGACTAATGATAATGGCAAAGTATTTGAAG");
+ IS(seq1.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ IS(seq2.quality, "\?==BBDFFGFHHGGIIIIFDCFC at FGHIIIIIIGIIIGHHGIFIIHIIIIIIGIIIGHFHHHGFFFFEEEEEEECECCDDDDDCDDCDCCCB\?ABDDDCDDDDACCDA>CCCDDDCEAA at ABBBB<>A>CCDCCDCBC><CAABC@@:@:");
+ }
+ else if (count==101)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq2.desc, "2:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq2.seq, "CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC");
+ IS(seq1.quality, "=\?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3\?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA\?ABCAC at 9@AA8\?\?8><ADB<>B8<B:C\?>@>>34>:@CD");
+ IS(seq2.quality, "=+=+<\?7@\?C0CACAABABABBAA=:<AABBBAAAAABBAABBBBAAAAA;\?@>>75>>=@>\?======;9;=8255+88=:\?\?\?\?\?\?\?\?\?=::=;<\?8883::8;8;;=;<=\?\?7<\?\?\?\?3;\?\?\?\?\?8;===\?\?\?\?\?\?###########");
+ }
+ else if (count==200)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq1.desc, "1:N:0:TTAGGC");
+ IS(seq2.desc, "2:N:0:TTAGGC");
+ IS(seq1.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq2.seq, "ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATGCATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCACGACTAATGATAATGGCAAAGTATTTGAAG");
+ IS(seq1.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ IS(seq2.quality, "\?==BBDFFGFHHGGIIIIFDCFC at FGHIIIIIIGIIIGHHGIFIIHIIIIIIGIIIGHFHHHGFFFFEEEEEEECECCDDDDDCDDCDCCCB\?ABDDDCDDDDACCDA>CCCDDDCEAA at ABBBB<>A>CCDCCDCBC><CAABC@@:@:");
+ }
+ }
+
+ IS(count, 200);
+ }
+
+ {
+ OK("test interleaved files");
+ vector<string> files;
+ files.push_back(TEST_SOURCE_DIR"/test_interleave.fastq.gz");
+ files.push_back(TEST_SOURCE_DIR"/test_interleave.fastq.gz");
+
+ htqc::MultiSeqFilePE fh(files, htio2::STRAND_FWD, htio2::STRAND_REV, htio2::COMPRESS_GZIP);
+
+ htio2::FastqSeq seq1;
+ htio2::FastqSeq seq2;
+
+ size_t count = 0;
+
+ while (fh.next_pair(seq1, seq2, htio2::STRAND_FWD, htio2::STRAND_REV))
+ {
+ count++;
+ if (count == 1)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq1.quality, "=\?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3\?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA\?ABCAC at 9@AA8\?\?8><ADB<>B8<B:C\?>@>>34>:@CD");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq2.desc, "2:N:0:CTTGTA");
+ IS(seq2.seq, "CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC");
+ IS(seq2.quality, "=+=+<\?7@\?C0CACAABABABBAA=:<AABBBAAAAABBAABBBBAAAAA;\?@>>75>>=@>\?======;9;=8255+88=:\?\?\?\?\?\?\?\?\?=::=;<\?8883::8;8;;=;<=\?\?7<\?\?\?\?3;\?\?\?\?\?8;===\?\?\?\?\?\?###########");
+ }
+ else if (count==100)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq1.desc, "1:N:0:TTAGGC");
+ IS(seq1.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq1.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq2.desc, "2:N:0:TTAGGC");
+ IS(seq2.seq, "ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATGCATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCACGACTAATGATAATGGCAAAGTATTTGAAG");
+ IS(seq2.quality, "\?==BBDFFGFHHGGIIIIFDCFC at FGHIIIIIIGIIIGHHGIFIIHIIIIIIGIIIGHFHHHGFFFFEEEEEEECECCDDDDDCDDCDCCCB\?ABDDDCDDDDACCDA>CCCDDDCEAA at ABBBB<>A>CCDCCDCBC><CAABC@@:@:");
+ }
+ else if (count==101)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq1.desc, "1:N:0:CTTGTA");
+ IS(seq1.seq, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(seq1.quality, "=\?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3\?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA\?ABCAC at 9@AA8\?\?8><ADB<>B8<B:C\?>@>>34>:@CD");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq2.desc, "2:N:0:CTTGTA");
+ IS(seq2.seq, "CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC");
+ IS(seq2.quality, "=+=+<\?7@\?C0CACAABABABBAA=:<AABBBAAAAABBAABBBBAAAAA;\?@>>75>>=@>\?======;9;=8255+88=:\?\?\?\?\?\?\?\?\?=::=;<\?8883::8;8;;=;<=\?\?7<\?\?\?\?3;\?\?\?\?\?8;===\?\?\?\?\?\?###########");
+ }
+ else if (count==200)
+ {
+ IS(seq1.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq1.desc, "1:N:0:TTAGGC");
+ IS(seq1.seq, "ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC");
+ IS(seq1.quality, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ IS(seq2.id, "HWI-ST1106:815:H154GADXX:1:1101:3431:2221");
+ IS(seq2.desc, "2:N:0:TTAGGC");
+ IS(seq2.seq, "ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATGCATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCACGACTAATGATAATGGCAAAGTATTTGAAG");
+ IS(seq2.quality, "\?==BBDFFGFHHGGIIIIFDCFC at FGHIIIIIIGIIIGHHGIFIIHIIIIIIGIIIGHFHHHGFFFFEEEEEEECECCDDDDDCDDCDCCCB\?ABDDDCDDDDACCDA>CCCDDDCEAA at ABBBB<>A>CCDCCDCBC><CAABC@@:@:");
+ }
+ }
+
+ IS(count, 200);
+ }
+}
diff --git a/t/t_multi_seq_file_se.cpp b/t/t_multi_seq_file_se.cpp
new file mode 100644
index 0000000..38bd1ed
--- /dev/null
+++ b/t/t_multi_seq_file_se.cpp
@@ -0,0 +1,52 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htqc/MultiSeqFile.h"
+
+using namespace std;
+
+void TestFramework::content()
+{
+ vector<string> files;
+ files.push_back(TEST_SOURCE_DIR"/test1.fastq");
+ files.push_back(TEST_SOURCE_DIR"/test2.fastq");
+ files.push_back(TEST_SOURCE_DIR"/test2.fastq");
+ files.push_back(TEST_SOURCE_DIR"/test1.fastq");
+ htqc::MultiSeqFileSE fh(files, htio2::COMPRESS_PLAIN);
+
+ htio2::FastqSeq seq;
+ size_t n_seq = 0;
+ while (fh.next_seq(seq))
+ {
+ n_seq++;
+ if (n_seq==1)
+ {
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq.desc, "1:N:0:CTTGTA");
+ }
+ else if (n_seq == 101)
+ {
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq.desc, "2:N:0:CTTGTA");
+ }
+ else if (n_seq == 201)
+ {
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq.desc, "2:N:0:CTTGTA");
+ }
+ else if (n_seq == 301)
+ {
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:1244:2196");
+ IS(seq.desc, "1:N:0:CTTGTA");
+ }
+ else if (n_seq == 302)
+ {
+ IS(seq.id, "HWI-ST1106:815:H154GADXX:1:1101:1197:2208");
+ IS(seq.desc, "1:N:0:TTGGTA");
+ }
+ }
+
+ IS(n_seq, 400);
+}
+
+
+
diff --git a/t/t_plain_file_handle.cpp b/t/t_plain_file_handle.cpp
new file mode 100644
index 0000000..ddd3906
--- /dev/null
+++ b/t/t_plain_file_handle.cpp
@@ -0,0 +1,64 @@
+#include "TestFramework.h"
+#include "TestConfig.h"
+#include "htio2/PlainFileHandle.h"
+#include <stdio.h>
+
+
+using namespace std;
+using namespace htio2;
+
+void TestFramework::content()
+{
+ PlainFileHandle fh(TEST_SOURCE_DIR"/test1.fastq", htio2::READ);
+ string line1;
+ string line2;
+ string line3;
+ string line4;
+
+ OK(fh.read_line(line1));
+ off_t off1 = fh.tell();
+ OK(fh.read_line(line2));
+ off_t off2 = fh.tell();
+ OK(fh.read_line(line3));
+ off_t off3 = fh.tell();
+ OK(fh.read_line(line4));
+ off_t off4 = fh.tell();
+
+ IS(line1, "@HWI-ST1106:815:H154GADXX:1:1101:1244:2196 1:N:0:CTTGTA");
+ IS(off1, 56);
+ IS(line2, "AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT");
+ IS(off2, 207);
+ IS(line3, "+");
+ IS(off3, 209);
+ IS(line4, "=?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA?ABCAC at 9@AA8??8><ADB<>B8<B:C?>@>>34>:@CD");
+ IS(off4, 360);
+ IS(ftell(fh.handle), 361);
+
+ fh.seek(off3, 0);
+ string line4again;
+ OK(fh.read_line(line4again));
+ IS(line4again, line4);
+
+ fh.seek(off1, 0);
+ string line2again;
+ OK(fh.read_line(line2again));
+ IS(line2again, line2);
+
+ fh.seek(off2, SEEK_SET);
+ fh.seek(off3-off2, SEEK_CUR);
+ IS(fh.tell(), off3);
+ IS(ftell(fh.handle), off3+1);
+ {
+ string line;
+ OK(fh.read_line(line));
+ IS(line, line4);
+ }
+
+ fh.seek(-151, SEEK_END);
+ IS(fh.tell(), 36000-151);
+ {
+ string line;
+ OK(fh.read_line(line));
+ IS(line, "@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD");
+ }
+}
diff --git a/t/t_ref_counted.cpp b/t/t_ref_counted.cpp
new file mode 100644
index 0000000..44ec7a8
--- /dev/null
+++ b/t/t_ref_counted.cpp
@@ -0,0 +1,42 @@
+#include "TestFramework.h"
+#include "htio2/RefCounted.h"
+
+using namespace htio2;
+
+class TestType: public RefCounted
+{
+public:
+ TestType(bool* flag): flag(flag) { *flag = true; }
+ virtual ~TestType() { *flag = false; }
+ bool* flag;
+};
+
+typedef SmartPtr<TestType> TestTypePtr;
+
+void TestFramework::content()
+{
+ bool live_flag = false;
+ TestType* obj = new TestType(&live_flag);
+
+ IS(obj->get_ref_count(), size_t(0));
+ IS(obj->get_ref_count(), obj->counter.get());
+ OK(live_flag);
+
+ obj->ref();
+ IS(obj->get_ref_count(), size_t(1));
+
+ {
+ TestTypePtr p1(obj);
+ IS(obj->get_ref_count(), size_t(2));
+ TestTypePtr p2(p1);
+ IS(obj->get_ref_count(), size_t(3));
+ TestTypePtr p3(obj);
+ IS(obj->get_ref_count(), size_t(4));
+ }
+
+ IS(obj->get_ref_count(), size_t(1));
+ OK(live_flag);
+
+ obj->unref();
+ OK(!live_flag);
+}
diff --git a/t/t_ring_buffer.cpp b/t/t_ring_buffer.cpp
new file mode 100644
index 0000000..dbe2259
--- /dev/null
+++ b/t/t_ring_buffer.cpp
@@ -0,0 +1,67 @@
+#include "TestFramework.h"
+#include "htio2/RingBuffer.h"
+
+#include <vector>
+#include <limits>
+
+using namespace htio2::juce;
+using namespace std;
+
+#define NUM_DATA 10
+
+htio2::RingBuffer<int> buffer(NUM_DATA * 2);
+
+struct MyWorker: public Thread
+{
+ MyWorker(const String& name): Thread(name)
+ {
+ result.reserve(4096);
+ }
+
+ virtual void run() override
+ {
+ for (;;)
+ {
+ int value = numeric_limits<int>::max();
+
+ if (buffer.pop(value))
+ {
+ printf("worker got %d\n", value);
+ if (value == -1)
+ return;
+
+ result.push_back(value);
+ }
+
+ yield();
+ }
+ }
+
+ vector<int> result;
+};
+
+
+void TestFramework::content()
+{
+ MyWorker worker("worker");
+ worker.startThread();
+
+ for (int value = 0; value < NUM_DATA; value++)
+ {
+ while (!buffer.push(value)) {Thread::yield();}
+ printf("pushed %d\n", value);
+ }
+
+ while (!buffer.push(-1)) {Thread::yield();}
+
+ worker.waitForThreadToExit(-1);
+
+ for (int value = 0; value < NUM_DATA; value++)
+ {
+ if (worker.result[value] != value)
+ {
+ fprintf(stderr, "expect %d, got %d\n", value, worker.result[value]);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
diff --git a/t/t_simple_seq.cpp b/t/t_simple_seq.cpp
new file mode 100644
index 0000000..41d9703
--- /dev/null
+++ b/t/t_simple_seq.cpp
@@ -0,0 +1,49 @@
+#include "TestFramework.h"
+#include "htio2/SimpleSeq.h"
+
+using namespace htio2;
+using namespace std;
+
+const char* SEQ = "TGGACGCAGCT";
+
+void TestFramework::content()
+{
+ {
+ string rev;
+ revcom(SEQ, rev);
+ IS(rev, string("AGCTGCGTCCA"));
+ }
+
+ SimpleSeq seq("seq1", "the quick brown fox jumps over a lazy dog", SEQ);
+ IS(seq.id, string("seq1"));
+ IS(seq.desc, string("the quick brown fox jumps over a lazy dog"));
+ IS(seq.seq, string(SEQ));
+ IS(seq.length(), size_t(11));
+
+ {
+ SimpleSeq rev;
+ seq.revcom(rev);
+ IS(rev.id, string("seq1"));
+ IS(rev.desc, string("the quick brown fox jumps over a lazy dog"));
+ IS(rev.seq, string("AGCTGCGTCCA"));
+ }
+
+ {
+ string sub;
+ seq.subseq(sub, 3);
+ IS(sub, string("ACGCAGCT"));
+ seq.subseq(sub, 3, 4);
+ IS(sub, string("ACGC"));
+ }
+
+ {
+ SimpleSeq sub;
+ seq.subseq(sub, 3);
+ IS(sub.id, string("seq1"));
+ IS(sub.desc, string("the quick brown fox jumps over a lazy dog"));
+ IS(sub.seq, string("ACGCAGCT"));
+
+ seq.subseq(sub, 3, 4);
+ IS(sub.seq, string("ACGC"));
+ }
+}
diff --git a/t/t_string.cpp b/t/t_string.cpp
new file mode 100644
index 0000000..f86b79c
--- /dev/null
+++ b/t/t_string.cpp
@@ -0,0 +1,58 @@
+#include "TestFramework.h"
+#include "htio2/StringUtil.h"
+
+#include <vector>
+
+using namespace std;
+
+void TestFramework::content()
+{
+ {
+ vector<string> result;
+ htio2::split("aaa\tbbb\tccc", '\t', result);
+ IS(result.size(), 3);
+ IS(result[0], "aaa");
+ IS(result[1], "bbb");
+ IS(result[2], "ccc");
+ }
+
+ {
+ vector<string> result;
+ htio2::split("\taaa\tbbb\t", '\t', result);
+ IS(result.size(), 4);
+ IS(result[0], "");
+ IS(result[1], "aaa");
+ IS(result[2], "bbb");
+ IS(result[3], "");
+ }
+
+ {
+ vector<string> result;
+ htio2::split("\t", '\t', result);
+ IS(result.size(), 2);
+ IS(result[0], "");
+ IS(result[1], "");
+ }
+
+ {
+ vector<string> result;
+ htio2::split("aaa", '\t', result);
+ IS(result.size(), 1);
+ IS(result[0], "aaa");
+ }
+
+ {
+ vector<string> result;
+ htio2::split("", '\t', result);
+ IS(result.size(), 0);
+ }
+
+ {
+ vector<string> input;
+ input.push_back("aaa");
+ input.push_back("bbb");
+ input.push_back("ccc");
+ string result = htio2::join("abc", input.begin(), input.end());
+ IS(result, "aaaabcbbbabcccc");
+ }
+}
diff --git a/t/t_text_file_equal.cpp b/t/t_text_file_equal.cpp
new file mode 100644
index 0000000..9192905
--- /dev/null
+++ b/t/t_text_file_equal.cpp
@@ -0,0 +1,14 @@
+#include "TestConfig.h"
+#include "TestFramework.h"
+
+using namespace std;
+
+void TestFramework::content()
+{
+ const char* file1 = TEST_SOURCE_DIR"/test1.fastq.gz";
+ const char* file2 = TEST_SOURCE_DIR"/test2.fastq";
+
+ OK(text_file_eq(file1, file1));
+ OK(text_file_eq(file2, file2));
+ OK(!text_file_eq(file1, file2));
+}
diff --git a/t/test1.fasta b/t/test1.fasta
new file mode 100644
index 0000000..ca10f46
--- /dev/null
+++ b/t/test1.fasta
@@ -0,0 +1,400 @@
+>HWI-ST1106:815:H154GADXX:1:1101:1244:2196 1:N:0:CTTGTA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAA
+GTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCT
+CCCACGTGTGGGAGCTTGTATGTACCTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:1197:2208 1:N:0:TTGGTA
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGAC
+GCCGCGTGAGTGAAGAAGTGGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATNNTGAC
+GGTACCTGACTAAGAAGCTCCGGCTAACTA
+>HWI-ST1106:815:H154GADXX:1:1101:1231:2209 1:N:0:ATCACG
+TAATTTTTTGTGTTTTGTTTTGTTATTTTCTTTGTTTTAAAATAAAAGCTCATCGCTGAA
+GCCACAGAAGCACATCACGTACCCTATGATTCTATAGAGAAGCTCAGTTTGTTTTTAAGT
+TTGTTTCTGAATAAGTAGAGCACCACATAG
+>HWI-ST1106:815:H154GADXX:1:1101:1225:2231 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATG
+ACGGTACCTGACTAAGAAGCCCCGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:1245:2247 1:N:0:ATCACG
+ACTCGTTATGATGCTTTAAAGCTTGCATATACGACATTACGTCAGGACGTCGTTGTCCAG
+AGTAGTACAAACGTAGGTCTATACTACTTTCATGTAGATTTACATCGAAAGAAGTTTAAT
+GCTGAAATCTATGACGTTCATGATTTAGCA
+>HWI-ST1106:815:H154GADXX:1:1101:1416:2204 1:N:0:GAACCT
+ATCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGAC
+GCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGAC
+GGTACCTAACAAGAAAGCACCGGCTAACTA
+>HWI-ST1106:815:H154GADXX:1:1101:1397:2205 1:N:0:TTAGGC
+AGCTCCTACGGGAGGCAGCAGGGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAA
+TGACGGTACCTGACTAAGAAGCACCGGCTA
+>HWI-ST1106:815:H154GADXX:1:1101:1258:2210 1:N:0:CAAGAA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAA
+GTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCG
+GGTATGGATACCCGTTTGCATGTACTTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:1454:2212 1:N:0:TGAGGT
+CAGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGC
+GACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAAT
+GACGGTACCTGACTAAGAAGCCCCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:1323:2213 1:N:0:CTACGG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGAC
+GCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAATGA
+CGGTACCTGACTAAGAAGCACCGGCTAAAT
+>HWI-ST1106:815:H154GADXX:1:1101:1432:2216 1:N:0:GACACT
+GACTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGATG
+CCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTAAGGGAAGAGGAAGGAC
+TGTACCTTACAAGAAAGCTCCGGCTAACTA
+>HWI-ST1106:815:H154GADXX:1:1101:1340:2224 1:N:0:CCTTAA
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCG
+ACGCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAAGCTCTATCAGCAGGGAAGATAGTG
+ACGGTACCTGACTAAGAAGCTCCGGCTAAA
+>HWI-ST1106:815:H154GADXX:1:1101:1400:2224 1:N:0:TTAGGC
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAA
+TGACGGTACCTGACTAAGAAGCACCGGCTA
+>HWI-ST1106:815:H154GADXX:1:1101:1493:2225 1:N:0:GTCGCT
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGCCGAGAGGCTGAACCAGCCAAG
+TCGCGTGAGGGATGAAGGTTCTATGGATCGTAAACCTCTTTTATAAGGGAATAAAGTGCG
+GGACGTGTCCCGTTTTGTATGTACCTTATG
+>HWI-ST1106:815:H154GADXX:1:1101:1376:2226 1:N:0:CCTTAA
+GACTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACG
+CCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACG
+GTACCTAACAAGAAAGCACCGGCTAACTAC
+>HWI-ST1106:815:H154GADXX:1:1101:1296:2233 1:N:0:TCATTC
+AAAAAACTGGAACAAGAAAGAAAACGTAAAATTGTTCCGCCGGAAATAACGACATGGTGG
+CGACTAGAATTGCAGTTACGAAGGGGAAAAGCAACTGATTGGCATGAGATGGTTCATGAA
+AGTTTGGATAGCTTTGCTAGTCCACAAGAT
+>HWI-ST1106:815:H154GADXX:1:1101:1467:2241 1:N:0:ATCACG
+CTGAATGCCTACAAAGGCTTCCTGTCGGATTATGCCTCCCTGCTGGACGAATTTGAAAAC
+GACAACCCCTTCAAAGCCAACTACCGGGTCTCGCTGAGCGTCATATGTGCCTGTTCTTCC
+TGCCATGACATTGGAATCAACATATACAGG
+>HWI-ST1106:815:H154GADXX:1:1101:1493:2245 1:N:0:GGCCTT
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCA
+AGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTG
+AGTCTCGTGAGACTTTTTGCATGTACCTTA
+>HWI-ST1106:815:H154GADXX:1:1101:1696:2195 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGAC
+GCCGCGTGGAGGAAGAAGGTTTTCGGAGTTTAAACTCCTGTCGTTAGGGACGATAATGAC
+GGTACCTAACAAGAAAGCACCGGCTAACTA
+>HWI-ST1106:815:H154GADXX:1:1101:1646:2204 1:N:0:CATCTA
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGC
+CAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAG
+TCGGGTATGCATACCCGTTTGCATGTACTT
+>HWI-ST1106:815:H154GADXX:1:1101:1502:2205 1:N:0:TTAGGC
+ATGATTTGCGCTCCCATATCTATCAGCTTGTCCACAAAGAACAAACGGCTTTCGAACATT
+TTCTGATGAATGAGTACACTGCCTTTTGCCTGGGTGGCAACCACCAGCAGCACACTGAGC
+AAGTCTGGTGTCAGTCCGGGCCAGGGTGCG
+>HWI-ST1106:815:H154GADXX:1:1101:1742:2207 1:N:0:CATCTA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAG
+TAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAG
+CCACGTGTGGCTTTTTGTATGTACCGTATG
+>HWI-ST1106:815:H154GADXX:1:1101:1683:2207 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGAC
+GCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGAC
+GGTACATAACAAGAAAGAACCGGCTCACAA
+>HWI-ST1106:815:H154GADXX:1:1101:1541:2208 1:N:0:ATCACG
+AATTCTAGAAATCACTCGCTGGTTTCGCCTAAAAATAGTAACTTTGCACCCAACAAAAAG
+AAACCAAAGACATTATGAACATTAAGAATATCCATTTGGCCTATTTTAGTGCCACTTTCT
+CCACCAAACGTATCGTTCGTGAGATAGCAT
+>HWI-ST1106:815:H154GADXX:1:1101:1564:2216 1:N:0:CAGATC
+AAAACGCCAAAGATAGTATTGACAGAACGCTAGCAAACGAAGCAGGTGTATCTTTAGAAG
+TATTGACTCCTTTGGAAGGATTGACGAATGAACAAATAGAAAATGGAGAAAACTATCTTT
+CTATCATGGAAGCAAACCTCGAAGCGAGAT
+>HWI-ST1106:815:H154GADXX:1:1101:1719:2228 1:N:0:CTACGG
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAG
+TAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAG
+GCACGTGTGCCTTTTTGTATGTAACGTATG
+>HWI-ST1106:815:H154GADXX:1:1101:1844:2204 1:N:0:CACTTG
+GACTACGGGAGGCAGCAGTGGGGAATCTTCCGCAATGGGCGAAAGCCTGACGGAGCAACG
+CCGCGTGAGTGAAGAAGGTCTTCGGATTGTAAAGCTCTGTTGTACATGACGAATGTGCCG
+GTTGTGAATAATGGCTGGCAATGACGGTAG
+>HWI-ST1106:815:H154GADXX:1:1101:1890:2219 1:N:0:GCCAAT
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACG
+CCGCGTGAGTGAAGAAGTAGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACG
+GTACCTGACTAAGAAGCTCCGGCTAAATAC
+>HWI-ST1106:815:H154GADXX:1:1101:1802:2224 1:N:0:CGTCAA
+GACTACGGGAGGCAGCAGTGGGGAATATTGGGCAATGGGGGAAACCCTGACCCAGCAACG
+CCGCGTGAAGGAAGAAGGCTTTCGGGTTGTAAACTTCTTTTACCAGGGACGAAGGGCGTG
+ACGGTACCTGGAGAAAAAGCCACGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:1840:2224 1:N:0:GTCGCT
+GGTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGCCA
+AGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTC
+GGGTATGCATACCCGTTTGCATGTACTTTA
+>HWI-ST1106:815:H154GADXX:1:1101:1923:2228 1:N:0:AAGCGA
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGA
+CGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAAT
+GACGGTACCTGACTAAGAAGCACCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:1769:2229 1:N:0:TTAGGC
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAA
+GTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCT
+CCCACGTGTGGGAGCTTGTATGTACCTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:1997:2231 1:N:0:TAGAAG
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAAGTCTGATGCAGCGACG
+CCGCGTGAGCGAAGAAGTAGTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACG
+GTACCTGACTAAGAAGCACCGGCTAAATAC
+>HWI-ST1106:815:H154GADXX:1:1101:1965:2235 1:N:0:CCACTC
+GTCATTTAGAGGAAGTAAAAGTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATC
+ATTACCGGGTGCGGGCCCTCTGGGTCCAACCTCCCATCCGTGTCTATCTGTACCCTGTTG
+CTTCGGCGTGGCCACGGCCCGCCGAAGACT
+>HWI-ST1106:815:H154GADXX:1:1101:1871:2243 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCC
+AAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGT
+GAGGCACGTGTGCCTTTTTGTATGTACCGT
+>HWI-ST1106:815:H154GADXX:1:1101:2118:2199 1:N:0:CAGCAC
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGA
+CGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATGA
+CGGTACCTGACTAAGAAGCCCCGGCTAACT
+>HWI-ST1106:815:H154GADXX:1:1101:2145:2206 1:N:0:CTATGG
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGA
+CGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAATG
+ACGGTACCTGACTAAGAAGCACCGGCTAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2188:2208 1:N:0:TGACCA
+GACTACGGGAGGCAGCAGTGGGGAATATTGGGCAATGGGCGCAAGCCTGACCCAGCAACG
+CCGCGTGAAGGAAGAAGGCTTTCGGGTTGTAAACTTCTTTTGTCGGGGACGAGTAGAAGA
+CGGTACCTGGCGAATAAGCCACGGCTAACT
+>HWI-ST1106:815:H154GADXX:1:1101:2116:2218 1:N:0:GAACCT
+GAACTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGGAACCCTGATGCAGC
+GACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAAT
+GACGGTACCTAACAAGAAAGCACCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:2046:2228 1:N:0:TTAGGC
+GGATATGAAAACATCGCTCCCGGTGATGCCATTTTCTTCGATTGGGATCTGGATGGTTCC
+GCAGACCATGTGGGAATTGTTGTCGGCACCGATGGCAGCCGTGTTTATACCGTGGAGGGA
+AATTCCGGCGATGCCTGCAAGATCAAAAGT
+>HWI-ST1106:815:H154GADXX:1:1101:2092:2229 1:N:0:AGTCAA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAA
+GTAGCGTGCAGGATGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGA
+GTCTCGTGAGACTTTTTGCATGTACCTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:2195:2237 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCG
+ACGCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAATCTCTATCAGCGGGGAAGATAGTG
+ACGGTACCTGATTAAGAAGCTCCGGCTAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2147:2238 1:N:0:CTACGG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCGAC
+GCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATGAC
+GGTACCTGACTAAGAAGCACCGGCTAAATA
+>HWI-ST1106:815:H154GADXX:1:1101:2498:2195 1:N:0:CTACGG
+ATCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCTAGCCTGAACCAGCC
+AAGTAGCGTGAAGGATGAAGGCTCTATGGGTCGTAAACTTCTTTTATATAAGAATAAAGT
+GCAGTATGTATACTGTTTTGTATGTATTAT
+>HWI-ST1106:815:H154GADXX:1:1101:2263:2198 1:N:0:ACTTGA
+GATCCTGAAGCAGAATTATCTGGTGTTTACCGGTATATCGGGGCTGGCGGTACAGTAAAA
+CGTCCGACTCAAGAAGGACCAGCTATTACTTTCAACAATATCAAAGGATTCCCCTGCACA
+CGGGTGAACATCGGAACAATGGCTAATCGT
+>HWI-ST1106:815:H154GADXX:1:1101:2307:2201 1:N:0:TGGATT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCG
+ACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATG
+ACGGTACCTGACTAAGAAGCACCGGCTAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2283:2204 1:N:0:CTACGG
+CGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCGAGCCTGAACCAGCC
+AAGTAGCGTGAAGGATGACGGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGT
+TTGGTATGCATACCATTTTGTATGTACCAT
+>HWI-ST1106:815:H154GADXX:1:1101:2453:2206 1:N:0:ATACAC
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAG
+TAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTTAG
+TCTCGTGAGACTTTTTGCATGTACCTTATG
+>HWI-ST1106:815:H154GADXX:1:1101:2336:2209 1:N:0:GTCGCT
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGCCA
+AGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATTAGAATAAAGTG
+CAGTATGTATACTGTTTTGTATGTATAATA
+>HWI-ST1106:815:H154GADXX:1:1101:2378:2210 1:N:0:CTACGG
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGC
+CAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAG
+TCGGGTATGTATACCCGTTTGCATGTACTT
+>HWI-ST1106:815:H154GADXX:1:1101:2470:2220 1:N:0:ATCACG
+TCTAACTGGGGCCGTAAGCGTTCGCTGATCTTTGCGGGTGTGATGTTCTTCATCTCTGCA
+TGGGGATCTATGTGTCCTGAGTCTTTGGTGTTGCCAAAGGGCGAACCTAATCTTACGCTT
+CTCATCGTGTTCAACCTCTATCGTGTGATT
+>HWI-ST1106:815:H154GADXX:1:1101:2434:2220 1:N:0:CGATGT
+GTAGAAGGTACTTATTTGTATAGTAAGAAAGATAATAATAGTTCACCTTTTATAATACGA
+ATTCATGCATATGCTGGAAAATCATATATTCGAGTGCTTCATACAATAACTTATACTGGT
+ATTCCTGACAAGCATAAAATAGAAAAGGGA
+>HWI-ST1106:815:H154GADXX:1:1101:2285:2223 1:N:0:CGAATA
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCA
+AGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTT
+AGCCACGTGTGGCTTTTTGTATGTACCGTA
+>HWI-ST1106:815:H154GADXX:1:1101:2390:2234 1:N:0:ATACAC
+CAACTCCTCGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCA
+ACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGAAAGAAAATG
+ACGGTACCTGACTAAGAAGCCCCGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:2331:2236 1:N:0:CAGCAC
+AGCTCCTACGGGAGGCAGCAGTCGGGAATATTGCGCAATGGAGGAAACTCTGACGCAGTG
+ACGCCGCGTGCAGGAAGAAGGCTTTCGGATTGTAAACTGCTTTAGACAGGGAAGAAACAA
+GACAGTACCTGTAGAATAAGCTCCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:2413:2237 1:N:0:CAGATC
+GTTAGAAGAAATAGCGGATCAATCGAGTGACACTCTTTCAGGCGGTCAACTCCAACGTGC
+GTATATTGCAATGGTGCTAGCGCAAGACACGGATTATATTTTACTGGATGAACCTTTGAA
+CAATCTAGATATGAATTTTGCGGTTCAAAT
+>HWI-ST1106:815:H154GADXX:1:1101:2368:2242 1:N:0:TCCTCA
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGAC
+GCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATG
+ACGGTACCTGACTAAGAAGCACCGGCTAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2491:2246 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTTAGGAATATTCGTCAATGGGGGAAACCCTGAACGAGCAAT
+GCCGCGTGAAGGATGACGGTCCTTTGGATTGTAAACTTCTGTTGGTAGGGAAGAACAAAC
+TGTATAGGAAATGATACAGTTCTGACGGTA
+>HWI-ST1106:815:H154GADXX:1:1101:2525:2193 1:N:0:CAGATC
+TCTAGAAAGCGCGTCTGTTTCATGTGCTTTCTATTATTTATCTTATGCCAATCCATTTCT
+TTGCTTTCCACAATTATATTGTGTAAAATTCAATTGTATAAAATATAATTAAAGGTGGTA
+ATTTTATGAAAAAAATGTATTCTACGAAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2680:2193 1:N:0:GAACCT
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAG
+TAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTTAG
+TCTCGTGAGACTTTTTGCATGTACCTTATG
+>HWI-ST1106:815:H154GADXX:1:1101:2516:2210 1:N:0:TAGCTT
+GACTACGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGT
+AGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGTTTTC
+CACGTGTGGAATTTTGTATGTACCATATGA
+>HWI-ST1106:815:H154GADXX:1:1101:2713:2212 1:N:0:TGACCA
+ACCGGCGTTATTAGTGGAACACAAACTATATGTGCAGGAAGTAGTACTACATTAAGTATC
+GCTGTAACCGGAACAGGTCCATGGAGCGGAACATTATCAAACGGTGATCCATTCAGTGGC
+AGCAGCAGCCCAATCAGTGTGTCAGTCAAT
+>HWI-ST1106:815:H154GADXX:1:1101:2678:2222 1:N:0:CGCTGA
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGC
+CAAGTAGCGTGCAGGATGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAG
+TGAGTCTCGTGAGATTTTTTGCATGTACCT
+>HWI-ST1106:815:H154GADXX:1:1101:2588:2225 1:N:0:CCTTCT
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGC
+CAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAG
+TCGGGTATGCATACCCGTTTGCATGTACTT
+>HWI-ST1106:815:H154GADXX:1:1101:2713:2231 1:N:0:TGACCA
+ACCGGCGTTATTAGTGGAACACAAACTATATGTGCAGGAAGTAGTACTACATTAAGTATC
+GCTGTAACCGGAACAGGTCCATGGAGCGGAACATTATCAAACGGTGATCCATTCAGTGGC
+AGCAGCAGCCCAATCAGTGTGTCAGTCAAT
+>HWI-ST1106:815:H154GADXX:1:1101:2557:2232 1:N:0:CAAGAA
+AAACTCCTTCGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGC
+CAAGGAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAG
+TCGGGCATGGATACCCGTTTGCATGTACTT
+>HWI-ST1106:815:H154GADXX:1:1101:2740:2237 1:N:0:AGTTCC
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGA
+CGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAAT
+GACGGTACCTGACTAAGAAGCACCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:2527:2244 1:N:0:GTTGAA
+CAACTCCTACGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCC
+AAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGT
+GAGGCACGCGTGCCTTTTTGTATGTACCGT
+>HWI-ST1106:815:H154GADXX:1:1101:2603:2248 1:N:0:CAGCAC
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCAAC
+GCCGCGTGAAGGATGACGGTTTTCGGATTGTAAACTTCTTTTCTTAGTGACGAAGACAGT
+GACGGTAGCTAAGGAATAAGCATCGGCTAA
+>HWI-ST1106:815:H154GADXX:1:1101:2853:2195 1:N:0:ACTTGA
+AATCGACAACAGGAACTGAAAAATGTTCTGAGAATTCTTTGATTTGCGGAAATCCGTTTC
+GCGTTCCTTGACCAACATAAAGAACTGGTTTTTTTGCTTTTTCAAGATAAGGCAAAGCAG
+CTAGCAAATCTTTTTCTTCTGGTAATATCA
+>HWI-ST1106:815:H154GADXX:1:1101:2884:2198 1:N:0:TGGATT
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGC
+CAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAG
+TGAGTCTCGTGAGACTTTTTGCATGTACCT
+>HWI-ST1106:815:H154GADXX:1:1101:2751:2204 1:N:0:AAGCTT
+TTTGTCATTTAGAGGAAGTAAAAGTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGG
+ATCATTACCGAGTGAGGGCCCTTTGGGTCCAACCTCCCACCCGTGTTTATTTTACCTTGT
+TGCTTCGGCGGGCCCGCCTTTACTGGCCGC
+>HWI-ST1106:815:H154GADXX:1:1101:2785:2207 1:N:0:AAGAAG
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGGGGGAAGAAGGATTTCGGAATGTAAAGTCCTGTCGGCAGGGAAGAAGATA
+ACGGTGCATCAGAAGAAGGAACAGGCGCAA
+>HWI-ST1106:815:H154GADXX:1:1101:2938:2209 1:N:0:CAGATC
+TATCACTTCGGAAAGTCCCTAACTGGCTACCGTCAAGATACTCCTGTTTTGCAAAACGAT
+TACCGGAGATAACTACTGTTCCTGCTCCCACAAGTTTAAAATTGGATAATCTGCTTTCTA
+TATATTCATCATATCTTCCTTCTTTTACTA
+>HWI-ST1106:815:H154GADXX:1:1101:2969:2210 1:N:0:CGTCAA
+AGCCTACGGGAGGCAGCAGGGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGCCAA
+GTAGCGTGAAGGATGACTGCCCTATGGGGTGTAAACTTCTTTTATAAAGGAATAAAGTCG
+GGTATGTATACCCGTTTGCATGTACTTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:2909:2214 1:N:0:CCGTCC
+ATTGCCTTTACCGATGGCATAATCTCAAAATATTCCACACCTACTATTACAACCGTAAGT
+CAGAGTGGAATAAAAATGGGAAATAAAGCGGCAAAAATGCTAATAGAAAGACTCGAATCT
+GAGGAAAATGAAGAAGATGAAAACTATAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2888:2222 1:N:0:GTCGCT
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCAACG
+CCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACG
+GTACCTGACTAAGAAGCCCCGGCTAACTAC
+>HWI-ST1106:815:H154GADXX:1:1101:2873:2233 1:N:0:ACTTGA
+CTAGAACAAGCAATAACAACTGTAAAACAAACAGTTACAGAGCTAAATGAAAAACAAGAG
+AAGAACCAGTCAGTTATCAAAAGTTTGGACGATCAACTTTCAAAAGGAATACTAAAAGCT
+CCTGTATCTGGAACGGTTCATTTAAATGAA
+>HWI-ST1106:815:H154GADXX:1:1101:2990:2243 1:N:0:GTCGCT
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGAGGAAACTCTGATGCAGCGAC
+GCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGAC
+GGTACCTGACTAAGAAGCCCCGGCTAACTA
+>HWI-ST1106:815:H154GADXX:1:1101:2791:2243 1:N:0:CAGATC
+ATCCAAAAATCCGCCACCCCATATCCAGTGGCAAACAGGGAAATAAATCAGCAGATTCCA
+AAAAATAACAAGTATAATATAGCCTTTTAAATTCAATCTCCCTGCAAAAGCTCCTGTCAT
+CAAAGGAACGGTAATCACGATAAACATCAG
+>HWI-ST1106:815:H154GADXX:1:1101:3046:2196 1:N:0:AGTTCC
+CAACTCCTCGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGCGAGTCTGAACCAGCC
+AAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGT
+TATCCACGTGTGGATTTTTGTATGTACCAT
+>HWI-ST1106:815:H154GADXX:1:1101:3147:2203 1:N:0:GGCCTT
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGA
+CGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGACAGTGA
+CGGTACCTGACTAAGAAGCTCCGGCTAAAT
+>HWI-ST1106:815:H154GADXX:1:1101:3211:2211 1:N:0:AGTGGT
+GATCCTCGGGAGGCAGCAGTGAGGAATATTGGTCGATGGACGAGAGTCTGAACCAGCCAA
+GTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGA
+GTCTCGTGAGACTTTTTGCATGCACCTTAT
+>HWI-ST1106:815:H154GADXX:1:1101:3127:2215 1:N:0:ATCACG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGAC
+GCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAAGCTCTATCAGCAGGGAAGATAGTGAC
+GGTACCTGACTAAGAAGCTCCGGCTAAATA
+>HWI-ST1106:815:H154GADXX:1:1101:3233:2216 1:N:0:TTGGTA
+AGCCTACGGGAGGCAGCAGTAGGGAATCTTCCGCAATGGACGCAAGTCTGACGGAGCAAC
+GCCGCGTGAGTGAAGAAGGTTTTCGGATCGTAAAACTCTGTTGTTAGAGAAGAACAAGTG
+CTAGAGTAACTGTTAGCGCCTTGACGGAAT
+>HWI-ST1106:815:H154GADXX:1:1101:3185:2216 1:N:0:TTGGTA
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCAA
+CGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGA
+CGGTACCTGACTAAGAAGCCCCGGCTAACT
+>HWI-ST1106:815:H154GADXX:1:1101:3012:2219 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCA
+ACGCCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATG
+ACGGTACCTGACTAAGAAGCCCCGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:3071:2234 1:N:0:CTACGG
+AGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCC
+AAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGT
+GGAGTATGCATACTCCTTTGTATGTACCGT
+>HWI-ST1106:815:H154GADXX:1:1101:3245:2235 1:N:0:CCTTAA
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATG
+ACGGTACCTAACAAGAAAGCACCGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:3136:2239 1:N:0:TTGGTA
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCG
+ACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATG
+ACGGTACCTAACAAGAAAGCACCGGCTAAC
+>HWI-ST1106:815:H154GADXX:1:1101:3036:2243 1:N:0:CAAGAA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAG
+TAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGG
+GTATGGATACCCGTTTGCATGTACTTTATG
+>HWI-ST1106:815:H154GADXX:1:1101:3201:2246 1:N:0:CTGTCA
+CGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGCC
+AAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGT
+TTTCCACGTGTGGAATTTTGTATGTACCAT
+>HWI-ST1106:815:H154GADXX:1:1101:3089:2248 1:N:0:ACTTGA
+GAACCCATATGTTCTTTTCTGCAATATTCCTCGAGCCATCGTTGTGATATTGGTCAAGTC
+AATAAAAGCAATGACTTCTGTCAGCAATTCTTGATATCCTAGCTTATCGGCAAGCCGTCG
+CTGCTCTGTCAAAAACTGTCGATCATAAAT
+>HWI-ST1106:815:H154GADXX:1:1101:3466:2192 1:N:0:CGATGT
+ATCGCGCCTTTAAGTCAGCCTGCAGGAAACAGTACGTTGACTTTAACCTCCTTTGATAAT
+GACCAACACCATGAAGTAGATCTGGTAAACATAGCTCGATTGGGCCGTCAATGGTTTGGC
+GAATCATTTGAGGTTAAAAACGAACAGGAA
+>HWI-ST1106:815:H154GADXX:1:1101:3490:2192 1:N:0:TAATCG
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACG
+CCGCGTGAGCGAAGAAGTATTTCGGGATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGA
+CGGTACCTGACTAAGAAGCACCGGCTAAAT
+>HWI-ST1106:815:H154GADXX:1:1101:3418:2203 1:N:0:TCACAA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGTCGGCAGACTGAACCAGCCAAG
+TCGCGTGAGGGAAGACGGCCCTACGGGTTGTAAACCTCTTTTGTCGGAGAGTAAAGTACG
+CTACGTGTAGTGTATTGCAAGTATCCGAAG
+>HWI-ST1106:815:H154GADXX:1:1101:3308:2210 1:N:0:TTGGTA
+AGCCTCGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGC
+CGCGTGGAGGAAGAAGGTTTTCGGATTGCAAACTCCTGTCGTTAGGGACGATAATGACGG
+TACCTAACAAGAAAGCACCGGCTAACTACG
+>HWI-ST1106:815:H154GADXX:1:1101:3481:2217 1:N:0:ATCACG
+GGGTAAAAGACTGGGCTAAGGAGAATGATTGCTGGATTGAAAATCCGGAATCATTAGGTG
+TGTTCTCTGACCGAGGTTCAGAGAACGAGGTTTATATGGCCTATGATGGAATACACGTTT
+ATAAACTTTACGACTTCCGTTATTCTGACG
+>HWI-ST1106:815:H154GADXX:1:1101:3392:2219 1:N:0:ATCACG
+GGGTACGACGCACATAACGCCCAGGGTGGAGAACTTGCCGAAATTCTTAGGTCCTACGAG
+GCTGATCGTAGCAGCGGCCAGAAGGACGCCGATTGTAGCCAGGCAGACTTCAACCGGATC
+AAGGTTGAAACCGAAAACATAAGAACCGTA
+>HWI-ST1106:815:H154GADXX:1:1101:3431:2221 1:N:0:TTAGGC
+ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTT
+CTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATT
+GGGCTAGGTTGGGGATCTTCATTTGTCCAC
diff --git a/t/test1.fastq b/t/test1.fastq
new file mode 100644
index 0000000..f42a110
--- /dev/null
+++ b/t/test1.fastq
@@ -0,0 +1,400 @@
+ at HWI-ST1106:815:H154GADXX:1:1101:1244:2196 1:N:0:CTTGTA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT
++
+=?@DFADDHHAHDGGBGGGIGHBEGGHEI>FGIIGCGGCH3?@FEB@@@FGICHG==AHFFEFEEDDDDDDC<>A>A:ACDCC>C<@BB>C at ACC@CACAC at ACCDDDCA?ABCAC at 9@AA8??8><ADB<>B8<B:C?>@>>34>:@CD
+ at HWI-ST1106:815:H154GADXX:1:1101:1197:2208 1:N:0:TTGGTA
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTGGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATNNTGACGGTACCTGACTAAGAAGCTCCGGCTAACTA
++
+@@CFFDFFGHHHHJJHFHGHHGIIHIJJJJIHHJJJJGIGIJHIJGIICFC at ECEHAB@4=;@DBB8B at B:@:>C>>CCCD:?CDDDDBDEEEDCCDCDDCCCC@@ADD?BDBD##++8?@B9A9CDCCCCCDDCDCCD at C>BBDDCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1231:2209 1:N:0:ATCACG
+TAATTTTTTGTGTTTTGTTTTGTTATTTTCTTTGTTTTAAAATAAAAGCTCATCGCTGAAGCCACAGAAGCACATCACGTACCCTATGATTCTATAGAGAAGCTCAGTTTGTTTTTAAGTTTGTTTCTGAATAAGTAGAGCACCACATAG
++
++:?DDDDDDHAFDHI at FGEGGGHGIIIHIIEGIGIIIGHIGIIIHIGICGGIIIICFFGIIIIAHHEAE@?BCCCCCCCBCBBCCCCCCDCDCEDCAACCC<CCCCCCDDCBCCCBBCCDDC>?CCACC>:@CCCDCCCCCC<ABBBCCC
+ at HWI-ST1106:815:H154GADXX:1:1101:1225:2231 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAAC
++
+=1=BBDDDHH)@?187EFEFH:CDHHGFHGIIIIIIGIIHIICFG<CHHEDECCECCCCBB?=@BBBB7BBB3+>@CCCC:ADDECBBBBBCEECDCCCCC at CCCC>C?BBBBBBCCCC:>C at BBBBCCACCCCCCCCCABBB.9<BBCC
+ at HWI-ST1106:815:H154GADXX:1:1101:1245:2247 1:N:0:ATCACG
+ACTCGTTATGATGCTTTAAAGCTTGCATATACGACATTACGTCAGGACGTCGTTGTCCAGAGTAGTACAAACGTAGGTCTATACTACTTTCATGTAGATTTACATCGAAAGAAGTTTAATGCTGAAATCTATGACGTTCATGATTTAGCA
++
++BBFFDFFHHHHHJJJJIJJIHIJJJIIHIJIIJJJJJJJGIJGIJJJJAHIJIIGIJJHGHHHHFFFFFFDDEEDDDDDDEDDEDDDDEDDEDEEDCDDDCDDEDDDDDDDDDDDCCCCCCC at CCDCDDDEECDDDDDDEDCCDEDCDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1416:2204 1:N:0:GAACCT
+ATCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAACTA
++
+1+14=ADDFFFFFII7EBCFGIIIIIEIIIFFIIIIFFIIIBEFDDDDCCCBBBBBBBB at BBBBBBBBB<?@?BBBBBB>BBBBBBBBBBBEEDBBBBBBB at B?>@BBBB?>>?BBBBBB<@>BBBBBBB at B??BB:AB<?><><?BBBB
+ at HWI-ST1106:815:H154GADXX:1:1101:1397:2205 1:N:0:TTAGGC
+AGCTCCTACGGGAGGCAGCAGGGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTA
++
+=@;=4BBB?F<D at FE:EA?FH)CFGBBBBC8>ACCCC@>CCB at 6@BBCB<AC9>@:A at C7&005;@BB508?A5-9<>?C:>CA@>AB<?@C>CDECCC:::>ACCCCBBB0?@BCA9CCACCA89<<5@>C?9 at ACAC@399<8.99<B
+ at HWI-ST1106:815:H154GADXX:1:1101:1258:2210 1:N:0:CAAGAA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGGATACCCGTTTGCATGTACTTTAT
++
+BCCFFFFFFFFHHIJJJJJIJGGIJJIJIHIJIIIJJJIHGIJJJJJJJJHHHHHFFFFEDEEEDBDDDDDDDDDDDDDDDDDDDCDBCBDDDEEDCDDDC>CDDEEDCCDDDDDDCBCBBD<>CCCCCCACDD5ACDCEEDDDDBCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1454:2212 1:N:0:TGAGGT
+CAGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAA
++
+1=+4AAD?FFDHHHFHGIII at BFGHIEIGI<?GGIIIGGHDH at BEAHFHEFFDFFEECE@@@BCC at 55>@B<@CCCDC>CC>CCCC at CBB??@DDDECCCCACCCCCCCBB@<ABBAC(>CAA at B>B<CCCCAC>AC>CA?8<<<BBBBC
+ at HWI-ST1106:815:H154GADXX:1:1101:1323:2213 1:N:0:CTACGG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAATGACGGTACCTGACTAAGAAGCACCGGCTAAAT
++
+:?@DDDDDHAFFAGIBEECH at G=DHHIGIGBHCHIIGHIICBHHGIFHFHEEEDECCCBBBBBBBBB7???BBBBBCCCCEEE at C@<ABA at CDDAAACCCC>CACCBB>818AC?CCA>ACBBBB>@@ACCCACCC at 3>A9<9<<>BCCA
+ at HWI-ST1106:815:H154GADXX:1:1101:1432:2216 1:N:0:GACACT
+GACTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGATGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTAAGGGAAGAGGAAGGACTGTACCTTACAAGAAAGCTCCGGCTAACTA
++
+=1+ADDDDF>FFDIFEEFCEF:CGE6??DBDFF==FFA at FFEE?@D?A at ACCBBBABB@B?BB;BBB;<@BB?<<BBBBBB?A at B?BBBADE>@ABBBABB<<?B at AB@BBB?B(8<?@BBBBBBBBBAA>ABBBBBABBB09 at B<B?AB
+ at HWI-ST1106:815:H154GADXX:1:1101:1340:2224 1:N:0:CCTTAA
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACGGTACCTGACTAAGAAGCTCCGGCTAAA
++
+B@@DDDFDHHDDFHIJIJJJJ?HHJJJIIJJJIJJJJIIJJJJJJJJJJJJJIJJIHHHFDDDDDDDDDDDD:@CDDDDDCCD:BCB+>ABDDEEEDDCDDAACDEDDDDDDDDDDDDDEEDDDBABDDDDDDDDDDDCCDCDDDDBDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1400:2224 1:N:0:TTAGGC
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTA
++
+11:BBDDBFHHHFIIIIIIIIDGIIEGGIGGIIGIIIIIIIIIFGGHHHHEEEEECCCCB?BB at BBBBBBBBCBBBBBCCCCEEDECBBBBCDDEECCCCCCCCCECCBBBBBBBCCCCCCCCCBBB?<CCCCACCCCCCCC?A?B at BBB
+ at HWI-ST1106:815:H154GADXX:1:1101:1493:2225 1:N:0:GTCGCT
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGCCGAGAGGCTGAACCAGCCAAGTCGCGTGAGGGATGAAGGTTCTATGGATCGTAAACCTCTTTTATAAGGGAATAAAGTGCGGGACGTGTCCCGTTTTGTATGTACCTTATG
++
+ at C<DFFFFHHHDHIGAFGGIIIIIIIIIIIIHIGFG at FHIADAHIICGDDHEHHHFFFFDEDDBDDBBBBBBCDDDDCCACAADDCDDDDD?A?A?CDDCD>CCEEDCDA?8 at CDC>CCB>BBDDBDCAAC>8ACBB<@@ADECCCCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1376:2226 1:N:0:CCTTAA
+GACTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAACTAC
++
+@@CFFFFFHHHHHJJJJIHGIJIIIIJJJJJJJJJJJJJJJHHFFFFEEEEEEDDDDDDDDDDDDDDDDDDBDDDDDD>ACDDDDBDDDDEEEDDCDDDCC88>BDDDCDBDDDDDDDDDD9ABCCCCDDCDCDDCCCAA at DB@BCCDAC
+ at HWI-ST1106:815:H154GADXX:1:1101:1296:2233 1:N:0:TCATTC
+AAAAAACTGGAACAAGAAAGAAAACGTAAAATTGTTCCGCCGGAAATAACGACATGGTGGCGACTAGAATTGCAGTTACGAAGGGGAAAAGCAACTGATTGGCATGAGATGGTTCATGAAAGTTTGGATAGCTTTGCTAGTCCACAAGAT
++
+1:?DDDD;D?FHHGIDBBGFHGHGEFHIIIIFIGIIIIEGGD8FHHHHCHEHEC>CC>>?@?8=@B34 at CC:AACCC at C@?BBBBBBBBCCBCCBC>:>>A<>AC at A>A@>@:>CCA>(4::@>C48@@>ACCCC:>@::@A>ACCBBCA
+ at HWI-ST1106:815:H154GADXX:1:1101:1467:2241 1:N:0:ATCACG
+CTGAATGCCTACAAAGGCTTCCTGTCGGATTATGCCTCCCTGCTGGACGAATTTGAAAACGACAACCCCTTCAAAGCCAACTACCGGGTCTCGCTGAGCGTCATATGTGCCTGTTCTTCCTGCCATGACATTGGAATCAACATATACAGG
++
+1=144=BDFHFHHEIEGHHGIFFEFHIIGEGEIIJIGIJIGIIIIIGIJJIGGIIGHEIEGEHFDAC>B=BDCDDCDDDDDCCCCDBB59CCCDBBDDD@>?@ADCCDBCCCDCCCCCCCACCDCCDDDDDDDCCDCDDCCDDDEEDEDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1493:2245 1:N:0:GGCCTT
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGAGTCTCGTGAGACTTTTTGCATGTACCTTA
++
+CCCFFFFFHHHHHJJJJJGIFGGIJJIJJIJJJJJJJJJIJJJJJJJJJIJIJJJHHGGFFFFFFEDDDDDDDDBDDDBDDDDDDDCDDC at DDDEEDDCCD@CDDDDDCDDBDDCCDDEDDDDDDCDDDDDDDDDDDDDDDCCCEDDDCD
+ at HWI-ST1106:815:H154GADXX:1:1101:1696:2195 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGAGTTTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAACTA
++
+B@@DFDEFGHGHHIJEHIIIJCGIIIJIJJJIJIJJJJJJFH>D?@DDEEE>ACDDDBD;B<BDBDDD;BDDDABBC3?3>@?C-9?-<((+>CC::44 at A4229A<<?AB>BBDDD:>CBDBA at CCDCBCD<<CC3>A?<@9@<?CDDA
+ at HWI-ST1106:815:H154GADXX:1:1101:1646:2204 1:N:0:CATCTA
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGCATACCCGTTTGCATGTACTT
++
+=:+A?DD;F?6<8)8CGEFEFF@?GGAF at BFIIDFBDFCFFC@B<FFE;=DEFEE>D>?DC>A=AA;A>?@?<A>?BBAAAABBB:@A@:<BB<@@A>A4>:::ABBBDEDBA<BBBAB>BAB<@@>@ABDEBABB55?B?BBABBDDBD
+ at HWI-ST1106:815:H154GADXX:1:1101:1502:2205 1:N:0:TTAGGC
+ATGATTTGCGCTCCCATATCTATCAGCTTGTCCACAAAGAACAAACGGCTTTCGAACATTTTCTGATGAATGAGTACACTGCCTTTTGCCTGGGTGGCAACCACCAGCAGCACACTGAGCAAGTCTGGTGTCAGTCCGGGCCAGGGTGCG
++
+1=+44,=DDDDDDDE3ACFF at EICFI>EEEE>DDADIIACD at DDDDDDA:@7@;@=CDCDDEDAD at AD;@AA>A;AAAAAA>;>AA>AA>A>9<,09?<><<<<<>??<<<<8<<>AA>:A<<::>A>:9244>AAA>9?;>>28><<<;
+ at HWI-ST1106:815:H154GADXX:1:1101:1742:2207 1:N:0:CATCTA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAGCCACGTGTGGCTTTTTGTATGTACCGTATG
++
+@@@AD?DDHHFFHIIIIIIIIEGCGGFCCHGBGD?DHGIGHIIAHAHIIIIICGHHHHHEEEECCACBBCCBCCCCCC?C at ACCCCB9?B>CDDCCCCCCCCACDCBBBBBBC>CADCCCCCACB?BCBBBBBCCCBA:AD:>>C>@BAC
+ at HWI-ST1106:815:H154GADXX:1:1101:1683:2207 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACATAACAAGAAAGAACCGGCTCACAA
++
+@@?DDDDDFGHFFJJGAFAEFHIJDIIIIGI?4BFGHGGI?HADE)6?AAA6;@CCABDD;@BDDD;B>B?B?BB<CC@(+4?AB<+2<CCDCCDC+:>>@32(0<@CBABBD<?B:A################################
+ at HWI-ST1106:815:H154GADXX:1:1101:1541:2208 1:N:0:ATCACG
+AATTCTAGAAATCACTCGCTGGTTTCGCCTAAAAATAGTAACTTTGCACCCAACAAAAAGAAACCAAAGACATTATGAACATTAAGAATATCCATTTGGCCTATTTTAGTGCCACTTTCTCCACCAAACGTATCGTTCGTGAGATAGCAT
++
++=;DDD8DBHHBFICBHIIGIEFHIIFHEDFF at GIIDC9BCGHG<FHIBGIIIIGIIIIIII>E>C2?);.>A6;AAA>CCCCCCCCCCCDDECCDE(:ACCCCC4>:3:@CA@@>CCACCCCCBBBBB<@2>?<9<B9<BCB(:A>@AD
+ at HWI-ST1106:815:H154GADXX:1:1101:1564:2216 1:N:0:CAGATC
+AAAACGCCAAAGATAGTATTGACAGAACGCTAGCAAACGAAGCAGGTGTATCTTTAGAAGTATTGACTCCTTTGGAAGGATTGACGAATGAACAAATAGAAAATGGAGAAAACTATCTTTCTATCATGGAAGCAAACCTCGAAGCGAGAT
++
+11=DD?DDDDDDDEEEEEDA2+<F21:1:)1CDBD4?B?DDD6BCC(=8=@8ADEII)====7A?C);?@@AA>@;@55;>-;A:3<'5:AAAA38::>>>4++44>83<><>4(:AA>::A::::::>:>3<3>><?A?##########
+ at HWI-ST1106:815:H154GADXX:1:1101:1719:2228 1:N:0:CTACGG
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAGGCACGTGTGCCTTTTTGTATGTAACGTATG
++
+ at CCFFFFFHHDHHGBB;AFHH at GGHGBCGHIFFGHIIIHA?FBAFFDFHIICHIGFHGHDBD at CACDDDCDDACCC;ACDD:?:ACDAB at D@DE>:@>>CDCC@>:<@D<B?4 at C@@C>+<???08<A<:>>ACDDB844>C:(42<8:?
+ at HWI-ST1106:815:H154GADXX:1:1101:1844:2204 1:N:0:CACTTG
+GACTACGGGAGGCAGCAGTGGGGAATCTTCCGCAATGGGCGAAAGCCTGACGGAGCAACGCCGCGTGAGTGAAGAAGGTCTTCGGATTGTAAAGCTCTGTTGTACATGACGAATGTGCCGGTTGTGAATAATGGCTGGCAATGACGGTAG
++
+B?@FFFFFHHHGHJIFIGHIJJIJJJIJJJJJJIJIIJJJJJJGHEFFEFFDCBB at BCDDBDDCDDDDDCCDDDDDDBDDDDDDDDDDDDEEECCCDDDCD@CCDEDCDDDDDDC>AAC5>9<<<B at CCDDDACAC@>?9CCCA:8<<A9
+ at HWI-ST1106:815:H154GADXX:1:1101:1890:2219 1:N:0:GCCAAT
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTAGTTCGCTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACGGTACCTGACTAAGAAGCTCCGGCTAAATAC
++
+ at CCFFFFFHHHHHIIJJJJIJJJIIJJJJJHJJJJJJJJJIJIJJJIJJJJIJJJIHHFDDDBDDDDDDDCDEDDDDDDDDDEDDDDBDEEEEDDDDDDCDCDDCDDDDDDDDDDCDEDDDDDDDCDDCDDDDDDCCDDDBBBBDDDCED
+ at HWI-ST1106:815:H154GADXX:1:1101:1802:2224 1:N:0:CGTCAA
+GACTACGGGAGGCAGCAGTGGGGAATATTGGGCAATGGGGGAAACCCTGACCCAGCAACGCCGCGTGAAGGAAGAAGGCTTTCGGGTTGTAAACTTCTTTTACCAGGGACGAAGGGCGTGACGGTACCTGGAGAAAAAGCCACGGCTAAC
++
+<@?DDBDDHA:FFGB at EA<EHIIIIICFHGH@@GIIGIIIIIIIFHHFD;?D at AA;@;=>3?;780)2?C>8?8(>?BB at CCC8@BB<>5CDEC at CC>C3@@:+:(<@8<0&5<>&25@@BBBBBBBCCCB@@CBACBBBBCCBBBBBC>
+ at HWI-ST1106:815:H154GADXX:1:1101:1840:2224 1:N:0:GTCGCT
+GGTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGCATACCCGTTTGCATGTACTTTA
++
+=+:BDF?BFFHFFIIIIIGICFFHIIIIIIIIGHIGCHIIIIIIIIGIGIHHIIGHHHFFFFACECDDDDBDDDDDDDDDDDBCCCCCDDDDDDDDDDDDD at CDDDADDCDDDDDDCDDDDD<<@CDCDCD at CDBBDCBDEDCDEADDEC
+ at HWI-ST1106:815:H154GADXX:1:1101:1923:2228 1:N:0:AAGCGA
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTAA
++
+CC at FFFFFHHHGHJJJJJJICGHIJIGJJJJJJJJJJJJJJJJIJJHHHHFFFFFFEEDDDDDDDDDDDDDDDDDDDDDCCEDEDDD@BBDCDEDCCDDDDDDDECCDDD?@B?CA>CDCDCDDD>BBDCDCCCCCCCDDCDCDDDBD at D
+ at HWI-ST1106:815:H154GADXX:1:1101:1769:2229 1:N:0:TTAGGC
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGTCCTACGGATTGTAAACTTCTTTTATAAGGGAATAAACCCTCCCACGTGTGGGAGCTTGTATGTACCTTAT
++
+@@@DDFFFFHDFHIGHIEHFHGIJJJJJJIJJFHIJJJEGIJJJJJHGIIJJJJJHHHGFFFCDEDDDDDCDB at CCDDD:@ACCCBDD5<?:@DEDCDDCDCACDEEDDDBBDDDDDDDDDDDDDDDDDDDDBDBACDADEEDDEDCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1997:2231 1:N:0:TAGAAG
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAAGTCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTAGTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACGGTACCTGACTAAGAAGCACCGGCTAAATAC
++
+?@@FFFFFGHHHHJJJIIIJJIIJJIJJJJJJJJJJJJ*(7CHI2.=FGHIJJJJJHHFDDDDDDDDDD9;@DDDDDCD3>CDD3?BDDEEEEDDDDDDDDCDDDDDDBDDBDD>CDEDDD at BBCDDDDDCCDDDDD(9A at B>BDDDDED
+ at HWI-ST1106:815:H154GADXX:1:1101:1965:2235 1:N:0:CCACTC
+GTCATTTAGAGGAAGTAAAAGTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTACCGGGTGCGGGCCCTCTGGGTCCAACCTCCCATCCGTGTCTATCTGTACCCTGTTGCTTCGGCGTGGCCACGGCCCGCCGAAGACT
++
+?=BDFFFFHHHHHJJFGIIJHGIJJJJHJIJIIGHHHHJJHEHHIJGIJJJJGJJJDHIHHHHHEFBBADBB=?BDDDDDDCDCCDDDDDDDDDDDCDBD88ABDEECCCCDDDDCDDDDDDDD<<BBBBDBA?BBDDDD>BB>BBBBC@
+ at HWI-ST1106:815:H154GADXX:1:1101:1871:2243 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAGGCACGTGTGCCTTTTTGTATGTACCGT
++
+?@BDADDDHHHHHJJJJJJJJEGIIIHIIIIIIGHIGHIJIJJJJJGH=FHIIJJEEHHFFFFFEEECBDDDDDDDDDDDDDDDCDDDCB??B9CDED at ACCDDCDDEDDDD>BBCCDD at CDCDDDD@ABCBACCDDDDD<CDECDDDB<
+ at HWI-ST1106:815:H154GADXX:1:1101:2118:2199 1:N:0:CAGCAC
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATGACGGTACCTGACTAAGAAGCCCCGGCTAACT
++
+1=?DD?DFFFHFHIIIGBFDCGGHGHICHIEH>DGG;/9BGIIAGGA>E>;?@CEDCCC8?@B at 7>BBBBBCBBBBCCC:ACDDAC5<A8 at DCCD>44>44:@C>>AB?B8?8(>CC::>C?############################
+ at HWI-ST1106:815:H154GADXX:1:1101:2145:2206 1:N:0:CTATGG
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAATGACGGTACCTGACTAAGAAGCACCGGCTAAA
++
++:?DDFFDHHDFHIIIEHGDCGHIIIIIIIIIIIIIIGIIGIIIHIHHHHFFFFFFEECBB at BB@B;;BBBCCCCBCAC at CADDDCC2<?CCDEECCCCCCCCCDCCBBCBBBCCC>CCCCCBBCBBCCCCCCCCCCCCCCCB at BBCBCC
+ at HWI-ST1106:815:H154GADXX:1:1101:2188:2208 1:N:0:TGACCA
+GACTACGGGAGGCAGCAGTGGGGAATATTGGGCAATGGGCGCAAGCCTGACCCAGCAACGCCGCGTGAAGGAAGAAGGCTTTCGGGTTGTAAACTTCTTTTGTCGGGGACGAGTAGAAGACGGTACCTGGCGAATAAGCCACGGCTAACT
++
+8=?DDFFFHGHHHIIIIIIIIIIIIIIIIGIIIIIIIIIIIIIIIHHHGFFFFFDEEEDDDDDDDDDDDDDDDDDDDDDDDDDDDDBDDDDEEDCDDDDDD at ADBBDDBDDDBBBCCDDDDDD@DDDDDDDDBDDDDDDDDDDDDDDDCD
+ at HWI-ST1106:815:H154GADXX:1:1101:2116:2218 1:N:0:GAACCT
+GAACTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGGAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAA
++
++:=DDDDDDDDDDEE@=EE?DE:CDDAADDABB at CEICC@CIIID85:??<???AA>>A:57<;8>?>???>???>??>AA?AAA?A??>>?<>AABA>:>>::>><9??><><?3<<8::AA?>5<9:AAA<AA???>4>9<?;>?###
+ at HWI-ST1106:815:H154GADXX:1:1101:2046:2228 1:N:0:TTAGGC
+GGATATGAAAACATCGCTCCCGGTGATGCCATTTTCTTCGATTGGGATCTGGATGGTTCCGCAGACCATGTGGGAATTGTTGTCGGCACCGATGGCAGCCGTGTTTATACCGTGGAGGGAAATTCCGGCGATGCCTGCAAGATCAAAAGT
++
++=@DFFFFHHFHHJJJJJIGIEGCFHIGIJGIJIJHIJJJGGGIJJIHHIJJHJIJFIIGHIHHFFDCCCCEEDBCDDDCCBCABB>BBDDBB<BCCB?BBD>8ACDDDCDD?BD?BDD5ABDD>CCDDD9BB?CCCBCDCACCACDDC3
+ at HWI-ST1106:815:H154GADXX:1:1101:2092:2229 1:N:0:AGTCAA
+AGCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGCAGGATGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGAGTCTCGTGAGACTTTTTGCATGTACCTTAT
++
+CCCFFFFFHHGHHIJIJJJJJJJJIIJGIIJIHIIIJIJJFIIJJJIIIIHHHHFFFFFEDEDEEDDDDDDBDD at CCBDDDBDDCDDDA?BDDEECCDDDDACDDEDDDDBDDDDDDEDDDDDDDDDDDDDCDDDDDDDED@@CDDDCDA
+ at HWI-ST1106:815:H154GADXX:1:1101:2195:2237 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAATCTCTATCAGCGGGGAAGATAGTGACGGTACCTGATTAAGAAGCTCCGGCTAAA
++
+1:=DDEFABHCFADFDGFGHI?GHIHGIIIGHGIIII>DHIGGCFGGIIHIE at DECEHHE<B>;BDBDBBDDAC at CCACCDCDECA@C>8A3(4:4(++::>((4+(&09&00((++(+++:?@&8>::43AADC at CC>A:CCD<39 at C@
+ at HWI-ST1106:815:H154GADXX:1:1101:2147:2238 1:N:0:CTACGG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATGACGGTACCTGACTAAGAAGCACCGGCTAAATA
++
+ at B?DDEFFDHFHFJJGEGGGIIGHJIJJJIHJIJJJJJGGEHIIFHHHHHHFFFFFFDCDDDD<@DB>BBDDDDDDDDCCDEDDDDDDDDCDADDDCDDDAACCCDDDDDBDDDDDD at CDBBBB>CCDDDDCDDDC>CCCB>@BDBDDDE
+ at HWI-ST1106:815:H154GADXX:1:1101:2498:2195 1:N:0:CTACGG
+ATCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCTAGCCTGAACCAGCCAAGTAGCGTGAAGGATGAAGGCTCTATGGGTCGTAAACTTCTTTTATATAAGAATAAAGTGCAGTATGTATACTGTTTTGTATGTATTAT
++
+@@@FFFFFHFHHHJGGIEHIH at FFHIJJJIGIHGI@HIGGEHGBGIGIIIJHIFHHH?DFFEDEEEEDDDDDDDDDCCDCDBDDDDD>CBCC9>BBBCDCCCCDDDDDEEDACD=C>CC>>CC>CCCDDEEDEEEDCDDDBDEACCDCAB
+ at HWI-ST1106:815:H154GADXX:1:1101:2263:2198 1:N:0:ACTTGA
+GATCCTGAAGCAGAATTATCTGGTGTTTACCGGTATATCGGGGCTGGCGGTACAGTAAAACGTCCGACTCAAGAAGGACCAGCTATTACTTTCAACAATATCAAAGGATTCCCCTGCACACGGGTGAACATCGGAACAATGGCTAATCGT
++
+111=D?DDDDFB;AEFEECE<3AEG+A9E?<?)1?8D<DGI).-7A;54/='';A.;6;5('(((,''504>:4?3<?@B1(8444(+:>@A((:4@<:>:::@A(3(4::(:<(229(489&5 at 3?:>A@###################
+ at HWI-ST1106:815:H154GADXX:1:1101:2307:2201 1:N:0:TGGATT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGATAATGACGGTACCTGACTAAGAAGCACCGGCTAAA
++
+??@DDFDFDH@:FHGG at GIIH@EHII<D?D at DEDGCGGEIIEGGIBB<CCEFCFEDECAABBBB@@;@8 at BBCC9<<BCC:@C:BCCB8<@C>@:BCC at CCACCCACCBAB?B at A:>@CCCCBCBAB at ACCACCCCCCA>CC?BBB<?@@
+ at HWI-ST1106:815:H154GADXX:1:1101:2283:2204 1:N:0:CTACGG
+CGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCGAGCCTGAACCAGCCAAGTAGCGTGAAGGATGACGGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGTTTGGTATGCATACCATTTTGTATGTACCAT
++
++11ADDDDHHHDHIAAG=EFGG at FHCHHBBDDH@B*BBFHBBFHG8 at EEDEDCCCACAB@BCB at CCCBB=@BCCBCC4>B>BBBBCCCCBCBB9CD>>C:@@CCCC>3>CCAC?<CCCAD>C3<+(:>>CD>CCACCEC at 8:@A>:@@>4
+ at HWI-ST1106:815:H154GADXX:1:1101:2453:2206 1:N:0:ATACAC
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTTAGTCTCGTGAGACTTTTTGCATGTACCTTATG
++
+CCCFFFFDFAHHG at GGIIFFAFIIDEHDHC?GGHIIIIIGIEGEIHIGIIIIIIIGF>CDCEFFACC;AC=(9ABD at BDBDDDDCCD9?BDCDDC@>CC@@>CDDE@@BDDDDCCC at C@ACCCCDBDDDDDCDCCCBDECCDEECDCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2336:2209 1:N:0:GTCGCT
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATTAGAATAAAGTGCAGTATGTATACTGTTTTGTATGTATAATA
++
+;:?DDDDDFHHHFIIGIG at G?FFHIGIIIGIIIEGGIGIIIIEGGHGGIIIIHGHEEHEEED at A;@>BBBBCC at CCCCCCCCBACC>CB9?B0:ADA>CC@@CCCCDDDEECCC>CCCCCCCCCCED at DDDDECBCCCB<CCC>BBCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2378:2210 1:N:0:CTACGG
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGTATACCCGTTTGCATGTACTT
++
+ at C+BDDFDHFHHHIJJJJJJGGFHHJJJJJIIJJJIJJIIIIIEHEIJIGIHHHHEFFFFCEEDDDDCDDDDD:ABDD at CCDDDDD@CDDDCBDDDEDACDDCDDDDDE3 at ACBCDCCDCDDBDD2<CC>>CCBCCD0?A@>AAC>CDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2470:2220 1:N:0:ATCACG
+TCTAACTGGGGCCGTAAGCGTTCGCTGATCTTTGCGGGTGTGATGTTCTTCATCTCTGCATGGGGATCTATGTGTCCTGAGTCTTTGGTGTTGCCAAAGGGCGAACCTAATCTTACGCTTCTCATCGTGTTCAACCTCTATCGTGTGATT
++
+@@BFFFFFFHHFHJJJJJJGHGIIIIHEGIJIJIIGHIBHHHFFFFFDEFDEEEEEEDDDDCBDB?@BCDEEEFEDDDCDDCDADDCDBBDBDDDDDDDCDB at BDDDCCDDDDDDDDBDDDDDEEDDBDBBCDEDDDDCCDCD<AABDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2434:2220 1:N:0:CGATGT
+GTAGAAGGTACTTATTTGTATAGTAAGAAAGATAATAATAGTTCACCTTTTATAATACGAATTCATGCATATGCTGGAAAATCATATATTCGAGTGCTTCATACAATAACTTATACTGGTATTCCTGACAAGCATAAAATAGAAAAGGGA
++
++=?DDBDD2=<2CGEEBDCE:ACEHFIHIF?+CEFD?C:CEECD?D<?<<<<DG at F<?D7D?BDC=FGIGIB=CF:@;CEEED>;A;CEE>7;?)((.;>;>@@@(5>AAABB>A@@@3:@>@BAB at A?AA2?8 at B@BBDB>:+:??<@?
+ at HWI-ST1106:815:H154GADXX:1:1101:2285:2223 1:N:0:CGAATA
+GATCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTTAGCCACGTGTGGCTTTTTGTATGTACCGTA
++
++1=DDDDDHHHHHIIIIIIIEHIIIIIIIIIIIIIDFHHIIIIIIIIIIIIIIIIHHHHEEEEEECCCBBBCCBCCCCCCCCBCCCCCBCBBBCEECCCCCCCCCCECBBBBBBCCCCDCECCCCCBBBCBBBBBCCCB<CDDDDDCB at B
+ at HWI-ST1106:815:H154GADXX:1:1101:2390:2234 1:N:0:ATACAC
+CAACTCCTCGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCAACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGAAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAAC
++
+=??=DBEFHH at HDHGIGGF@F9EFA at FHEHIEHIIIGFHIIIIGIIHHGHFFFEDEACA>CB>?BBBB@;?B>>CD@>A?::BAD>C528?C>CD34>A:@>:>:4 at AABBBC?9?CCCCC:8>@BB:>>CCCCCCCCCA8<>BBB>?@C
+ at HWI-ST1106:815:H154GADXX:1:1101:2331:2236 1:N:0:CAGCAC
+AGCTCCTACGGGAGGCAGCAGTCGGGAATATTGCGCAATGGAGGAAACTCTGACGCAGTGACGCCGCGTGCAGGAAGAAGGCTTTCGGATTGTAAACTGCTTTAGACAGGGAAGAAACAAGACAGTACCTGTAGAATAAGCTCCGGCTAA
++
+8??DFBEDGHFAHGG?FHGIIFFHGGIGGHGEHGD<FBHIIAEGHGHH9EECF at 8>CD;;@;?@BDDDDDDDDDDBBBCDB1(9?A?B?BBCCDDDD::>C>CCCDCCCB??B at BDD?C at CCCDCDE@@C(+:@@CCCCCC at 3>9995<@
+ at HWI-ST1106:815:H154GADXX:1:1101:2413:2237 1:N:0:CAGATC
+GTTAGAAGAAATAGCGGATCAATCGAGTGACACTCTTTCAGGCGGTCAACTCCAACGTGCGTATATTGCAATGGTGCTAGCGCAAGACACGGATTATATTTTACTGGATGAACCTTTGAACAATCTAGATATGAATTTTGCGGTTCAAAT
++
+?8?;BDDDAD8+?<C18CFFAADFF>):?DF>:<DDFFEIII9F at 5-;=?EE at EEB5;?BC=,(;B;(5>::>(,5>@B#######################################################################
+ at HWI-ST1106:815:H154GADXX:1:1101:2368:2242 1:N:0:TCCTCA
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTAAA
++
+?B at FDFFFGHHGHIIJJJGHHIIJJIJJJJJJJJJJJJIJJJDIIJHHHGFCEFFEEDBDDDDDDDBBDDDDDBBDDC@CCCDDCD?ABDEEEEDDDDDDDCDECDDDDBDDDDDDDDDDDDDDBBBDDDDDDDDDDDDDDCDDDDDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2491:2246 1:N:0:CCTTAA
+AGCCTACGGGAGGCAGCAGTTAGGAATATTCGTCAATGGGGGAAACCCTGAACGAGCAATGCCGCGTGAAGGATGACGGTCCTTTGGATTGTAAACTTCTGTTGGTAGGGAAGAACAAACTGTATAGGAAATGATACAGTTCTGACGGTA
++
++:=DFDFFHH>AHGHI=GHHGFHIIIIIIIIIHIIIIIIIIIFIIIIIIH at HHDEFCCCCCCCBBBBB?B>C8ACCCBBBBBCCCCCCCCC at DDDCCCCCCECC+8ACCCCCBBCCCCBBCC:BDCCC<CCCCCCECCC:ACDCDCCB<?
+ at HWI-ST1106:815:H154GADXX:1:1101:2525:2193 1:N:0:CAGATC
+TCTAGAAAGCGCGTCTGTTTCATGTGCTTTCTATTATTTATCTTATGCCAATCCATTTCTTTGCTTTCCACAATTATATTGTGTAAAATTCAATTGTATAAAATATAATTAAAGGTGGTAATTTTATGAAAAAAATGTATTCTACGAAAA
++
+11+=BDDDFFFFFGIIIIIFIIFGIIFIEFIF*?GFGCFFEFIIFFFEEFFECFGIEIGIIIFIFFEEEEEEFECDEDEDD at A>BDECEBBBEDDB at DEED@BABEEEBD>ABAB:>?BABABDBBBBABBA?BBBB4@@BB>A:<BB@@
+ at HWI-ST1106:815:H154GADXX:1:1101:2680:2193 1:N:0:GAACCT
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTTAGTCTCGTGAGACTTTTTGCATGTACCTTATG
++
+CCCFFFFFHGHHHJJIIIHIIIIJJJJJJJJFGIJJJJJJJJJJJJJJJJJHHHHFFFFDEEEEDDDDDDDDBDDDDDDDDDDDDDDABDDDEEDD at CDDDCDDEEDDDADDDDDDECDDACDCDBBDBDDDDDDDDDEEDDCDDDDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2516:2210 1:N:0:TAGCTT
+GACTACGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGTTTTCCACGTGTGGAATTTTGTATGTACCATATGA
++
+;;@DDDD?DFHBFII;FHACBCFCGEGIHGCG at DFGGEHDGHABBCFG>FHGG at EDEEHFH@BBCC??;>BCCCC>>C?B:CCC>A9?<@CAD>C at CCC>A at CDC:@A?CBCCCC@@CC:>:>?BBCBBCCCCCCC(::>@DD>>4>4>C
+ at HWI-ST1106:815:H154GADXX:1:1101:2713:2212 1:N:0:TGACCA
+ACCGGCGTTATTAGTGGAACACAAACTATATGTGCAGGAAGTAGTACTACATTAAGTATCGCTGTAACCGGAACAGGTCCATGGAGCGGAACATTATCAAACGGTGATCCATTCAGTGGCAGCAGCAGCCCAATCAGTGTGTCAGTCAAT
++
+@@@FFFDFHHGHFIGIIHIJJHIIGJIJIIJJFIJJJJIJIIIJIJJJJJIJJIJJDHIIJHHHFFFDECCDDDDDBDDDDEDDDDDDDDDD at CDDEDEDDCBD<ABCDDDDEEDDDDDBDBDDABA?BDD?BCCDC at C:ABACCCACCD
+ at HWI-ST1106:815:H154GADXX:1:1101:2678:2222 1:N:0:CGCTGA
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGCAGGATGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGAGTCTCGTGAGATTTTTTGCATGTACCT
++
+B=@DDFFFHGFHHIGAFGEGHIGIIGIIJIIJJJIBHGIIIFJIJIJJIIJEEFH=BBFDDECDCDCDDDDDDDDBCDDCBDDB<BCDDDD?BBBDDEC at ACCDDDDDD@CDD<ABDCDDBCACACDCDBBDDCDDDDDDBDEECCEDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2588:2225 1:N:0:CCTTCT
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGATGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGCATACCCGTTTGCATGTACTT
++
+BB at FFFFFHHHHHJJJJIGIJJJJJIJJJJJJJJJHIIJIIIIJJJJJJJJJIIHHHHFFFFEDECEDDDDDDCDDDDDDDDCDDDDDDDDDBDBCEEDDDDDDDDDDDEECDDDDDDDADA@DD?BDDDEEDDDDD<ACBDDCDDEDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2713:2231 1:N:0:TGACCA
+ACCGGCGTTATTAGTGGAACACAAACTATATGTGCAGGAAGTAGTACTACATTAAGTATCGCTGTAACCGGAACAGGTCCATGGAGCGGAACATTATCAAACGGTGATCCATTCAGTGGCAGCAGCAGCCCAATCAGTGTGTCAGTCAAT
++
+?@@FFFFFHHGHGJHGIJIIJJJJJJJJIJIJGEHGIJJJJHIIIJJJIJJJJIIJHIJIJHHEFFDEEDDDDDDCDDDDDEDDDDDDDDDDBDDCEDECD><@2?BCCDDDEDDCCDDDDDDDDD at BBDDADCCC>4 at 4>ACCCDACDC
+ at HWI-ST1106:815:H154GADXX:1:1101:2557:2232 1:N:0:CAAGAA
+AAACTCCTTCGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGGAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGCATGGATACCCGTTTGCATGTACTT
++
+++:BDD>4=ADDDD at EEBE7C11:EDBED**?B?*B90??DDDCDDA<A9=;>CCC at D?;=A@@(;>=6,8?=:>>>A:A3:9+243>4:<3(&04(:3AAAA>:>A:(>A>A?AA##################################
+ at HWI-ST1106:815:H154GADXX:1:1101:2740:2237 1:N:0:AGTTCC
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTAA
++
++:?DDDDDDD@@DEEIE>FE:?BEDDD;?BDDAEEIDBDDII>@AD9?CD>@DDD;AA@>???65;;5>>?A???>?AA(:>BD3<-+8>>B:>BAAAA34>:>>>>28>8<88>A9>?AAAA??9>>AAAAAAAAAAAAA<??>>?>>A
+ at HWI-ST1106:815:H154GADXX:1:1101:2527:2244 1:N:0:GTTGAA
+CAACTCCTACGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGAGGCACGCGTGCCTTTTTGTATGTACCGT
++
+ at CCFFFFFHHGHHJIIGBHIJIJJJIIHIJJICEHIGHJJJJIIIIJJJJIIJGIJGHHHHFFFFFEDDDBDCCDCDDDDCDDDDDCCCDDBBDDDDDDACACDCDDEDA@BDDBDDDDCCDC@???DD>BDDDDCDDD@<CDDDDACDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2603:2248 1:N:0:CAGCAC
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCAACGCCGCGTGAAGGATGACGGTTTTCGGATTGTAAACTTCTTTTCTTAGTGACGAAGACAGTGACGGTAGCTAAGGAATAAGCATCGGCTAA
++
+?B+4=BDFHGHDDHIIJJJICFGGJJJIIIIJIGIIJJIFHGIIHIGHHCD>@DDEEDEABDDDDDDDDDDCBDDDDB at 5<>?CDDBDDDDEEED:ADCDDAC at CCD@ADDDDDDDDCCCCDD at D@B9AC>@CC>CDCDDDDAC>B at BBC
+ at HWI-ST1106:815:H154GADXX:1:1101:2853:2195 1:N:0:ACTTGA
+AATCGACAACAGGAACTGAAAAATGTTCTGAGAATTCTTTGATTTGCGGAAATCCGTTTCGCGTTCCTTGACCAACATAAAGAACTGGTTTTTTTGCTTTTTCAAGATAAGGCAAAGCAGCTAGCAAATCTTTTTCTTCTGGTAATATCA
++
+1:1BDDDDFH<BFHGIIIIIIEHHIIIGIIGHG at DHIIIIH>DHF?BGHGGIAHIIIIIIHBEECCCAC@;>ACB?BCCCCCA<?CCC>CBBBBBBC>CCCCCACCCCCCCCC?<A993?BC at AC>CCCCCCCCCCCC at CAC3:>C@@:@
+ at HWI-ST1106:815:H154GADXX:1:1101:2884:2198 1:N:0:TGGATT
+CAACTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGAGTCTCGTGAGACTTTTTGCATGTACCT
++
+@@@DDDDDFFHHHIIDD;FH?ECEEHGHIIGEBGEIIIIIIIIIIIIGHHIIGHIFEHHFEDEECCCCCBB6ACBB?ABCBBB>@B<CCCBA?@BCDDCCC3:>ACACDCCCA8AB at CACECCCCCCCABBCBC@@CC>ABC>AA@@D>>
+ at HWI-ST1106:815:H154GADXX:1:1101:2751:2204 1:N:0:AAGCTT
+TTTGTCATTTAGAGGAAGTAAAAGTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTACCGAGTGAGGGCCCTTTGGGTCCAACCTCCCACCCGTGTTTATTTTACCTTGTTGCTTCGGCGGGCCCGCCTTTACTGGCCGC
++
+B?=DDDFFHHHHHJJJJJJJJJJJJJJJJJJJJJJIJJJJJJJJJJJJIIJJJJJJJJIJGHHHHHFEFFDDDDDDDBDDDDDDDDDBDDDDDDDDDDDDDB@<@<BDDDDEEEDDDDACCACDDD9BDDDD>BD59>09A(44+:1?50
+ at HWI-ST1106:815:H154GADXX:1:1101:2785:2207 1:N:0:AAGAAG
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGGGGAAGAAGGATTTCGGAATGTAAAGTCCTGTCGGCAGGGAAGAAGATAACGGTGCATCAGAAGAAGGAACAGGCGCAA
++
+BCCDDFFDHHFFFIIIGHGIH at GGEI@GHIJJJGIJJIJIJIJHDEFFEDECCDDCDCCDDDDDDBDD at B7&&059BDDDD8ACCCDD+(2@>CDE>((4@(4 at 0&&5<BD72?####################################
+ at HWI-ST1106:815:H154GADXX:1:1101:2938:2209 1:N:0:CAGATC
+TATCACTTCGGAAAGTCCCTAACTGGCTACCGTCAAGATACTCCTGTTTTGCAAAACGATTACCGGAGATAACTACTGTTCCTGCTCCCACAAGTTTAAAATTGGATAATCTGCTTTCTATATATTCATCATATCTTCCTTCTTTTACTA
++
+=@1BBDDFGAHDHII:EG at DHGHEFHA?EFFAH:DGFHGIGCGIHIGGI;DGGHIGIGEGIHCEEB>CCCCCCCCACCDCC at CCCCCCCCB?ABCCEECCCDCAACACCC@:@:4 at C@CCDCCDEDC:A>:CACCDC>>A at CCCCCCCC3
+ at HWI-ST1106:815:H154GADXX:1:1101:2969:2210 1:N:0:CGTCAA
+AGCCTACGGGAGGCAGCAGGGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGGTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGTATACCCGTTTGCATGTACTTTAT
++
+;?@DDD>DHA?FDGEHIGG)?:CGIGIIICGIGEHD at FHICGGGGBHH>CDCEDC;;;??;5;A at B;?BBCCBCCCCCCCC?CCCCC8(5<BCDACCCCCC@@@CA>CAC?CCCCAC>CBBB at BCCCDEE>CA99?CBCCDC>4:@BDC@
+ at HWI-ST1106:815:H154GADXX:1:1101:2909:2214 1:N:0:CCGTCC
+ATTGCCTTTACCGATGGCATAATCTCAAAATATTCCACACCTACTATTACAACCGTAAGTCAGAGTGGAATAAAAATGGGAAATAAAGCGGCAAAAATGCTAATAGAAAGACTCGAATCTGAGGAAAATGAAGAAGATGAAAACTATAAA
++
+@<@FFFFFHFHHHIJJIJIIGJJJIJJJJJIIIJIJJFJJJJJIJIIG>GHJIJJGIGICGGIIGCHHHHGFFFFFFEEECCDDDADDDBBDDDDDBDDDDCDDDDDDDDDDDDDDDDDDEDDDDDDDDDDDDDDDDCD at CDDDDDDDDE
+ at HWI-ST1106:815:H154GADXX:1:1101:2888:2222 1:N:0:GTCGCT
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCAACGCCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAACTAC
++
+@@@DDBD>AF1?;F=132<?FF at GFCFEDDF?9?DGD?@F6AAB8AAEFFC;;?B;BCBCB at B=@;>?BB>BDBAAB4@>::@BBBBBB:@BBAAABBBBBA@@BBB>B?2(3??>>:A<@085A4:?AAABA at BBA@B><@BBBB?BB>
+ at HWI-ST1106:815:H154GADXX:1:1101:2873:2233 1:N:0:ACTTGA
+CTAGAACAAGCAATAACAACTGTAAAACAAACAGTTACAGAGCTAAATGAAAAACAAGAGAAGAACCAGTCAGTTATCAAAAGTTTGGACGATCAACTTTCAAAAGGAATACTAAAAGCTCCTGTATCTGGAACGGTTCATTTAAATGAA
++
+8:?=A=?D8F?<DFF:<:A3AFAFFEHEFB?FFACCF>>F4?BFGIIIIIEDGF<;CF at FFFI=;=CEIIEFF>?EB>DBDD>.;@BB(5;=?9?BBB5>:>A:ABB2>A>>ABBBB>?>@:AA:@@::@:@@B9<+2<A:B>BAABD@@
+ at HWI-ST1106:815:H154GADXX:1:1101:2990:2243 1:N:0:GTCGCT
+AGCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAACTA
++
+CCCFFFFFHHGHHJJJJJIIIIJJJJJJJJJJIIJJJJJJJJJJJIJHHGHHHFFFFCCDDDDDCB at DDDDDCDDDDDCDEEDEDDBBDCDDCDDDDDDDDCDEDDDDDDDDDDDDDDDDDD<?@CDDDDDDDDDDCCDDDBDBDDDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2791:2243 1:N:0:CAGATC
+ATCCAAAAATCCGCCACCCCATATCCAGTGGCAAACAGGGAAATAAATCAGCAGATTCCAAAAAATAACAAGTATAATATAGCCTTTTAAATTCAATCTCCCTGCAAAAGCTCCTGTCATCAAAGGAACGGTAATCACGATAAACATCAG
++
++=?DA??D:C:<C=BEEDEEEIDBCEEE9?DDADBDDD at B(9BDEEICC3=788A==ACEEC;A?@:A>@>@(65>BBA>DB<>AAAAAAAD>AADEAA>A>>A??AA?A?AAA>A>AA>AAAAA?>A>?>2<>AA>A<<8<>AAAAAAA
+ at HWI-ST1106:815:H154GADXX:1:1101:3046:2196 1:N:0:AGTTCC
+CAACTCCTCGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGCGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGTTATCCACGTGTGGATTTTTGTATGTACCAT
++
+CCCFFFFFHHHHHJJJJJJJJGIJJJJJJJJJJJJJJJJJJJJJJIJJHHHHFFFFFDDDEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCDDDDEEDDCDDDDDDDEEDDDDDDCDDDCCEECCCCDBDCDDCDDDDDDADDDEEEDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3147:2203 1:N:0:GGCCTT
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGACAGTGACGGTACCTGACTAAGAAGCTCCGGCTAAAT
++
+@@@FFDDFHH8FDGBIGECHFGGGGIGIJIIGGIJIGGIGHGGFHECH at AGGDGIIIGHBEDDDDD@DDDDDCCDDDDD@@DECDDDDABA>@CCCCDCCCACDECCBDDDD?A?ACACCCDD at BBDDCDCDDD@CCAC at CCDBDBDDDC
+ at HWI-ST1106:815:H154GADXX:1:1101:3211:2211 1:N:0:AGTGGT
+GATCCTCGGGAGGCAGCAGTGAGGAATATTGGTCGATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGCAGGAAGACGGCCCTATGGGTTGTAAACTGCTTTTATAAGGGAATAAAGTGAGTCTCGTGAGACTTTTTGCATGCACCTTAT
++
+@@CFFFFFHFHHHJJJJJJJJJJJIJJIJJJJHHJIGIJJJJJIIIJJJJJGGHHFFFFEDEEEEBDDDDCDDDDDDBBDDDDCDDDDCBDDDEEDDDDDDCDDDEECDDBBDCDDD@>ACDDDDDDDDDDDCDDDDDDEEC:ACDDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3127:2215 1:N:0:ATCACG
+AGCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGAGGAAACTCTGATGCAGCGACGCCGCGTGAGTGAAGAAGTAATTCGTTATGTAAAGCTCTATCAGCAGGGAAGATAGTGACGGTACCTGACTAAGAAGCTCCGGCTAAATA
++
+1:?DBD8DFF@@FHA=7BF at GHIIGHCAHEEH@>GH9DHDEHHIIHIICGGDGID;==BBA?B8;>>BBB>CCD at CC?>ACDEC?3>??ACDECCA4>>CC>@DA>?@B8 at 78ACC:AACBB5@<>4:?9 at 4>:>C39:@>.559?CC:>
+ at HWI-ST1106:815:H154GADXX:1:1101:3233:2216 1:N:0:TTGGTA
+AGCCTACGGGAGGCAGCAGTAGGGAATCTTCCGCAATGGACGCAAGTCTGACGGAGCAACGCCGCGTGAGTGAAGAAGGTTTTCGGATCGTAAAACTCTGTTGTTAGAGAAGAACAAGTGCTAGAGTAACTGTTAGCGCCTTGACGGAAT
++
+@@@BDDD6?FADDI=BBHGFGGGG at BA?FBFEHII6:BDG at FGGGADG>?;CE6B8<?CA at BBBBB>BBBCCCCCCC929::<CB&(25 at CB?@C<:CCAC:C<BCCCCCC?9AC93(4@:4>AA:::A:A4+4>>@9.9>>CC>9@###
+ at HWI-ST1106:815:H154GADXX:1:1101:3185:2216 1:N:0:TTGGTA
+GATCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCAACGCCGCGTGAGTGAAGAAGTATTTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAACT
++
+@@CFFFFFHHDFHGIGHIGGFGIIJJJIJJIIJIJJJGIJJJIJIIHHHGDFFDFDCEEECBDDBDBB at BD@CCDDDCD>CDEEEDD?BDDDEEECDDDDDCCDDDDDDDDDDDDDCDDDDDDDDDDDDDDCCDDDDDDDDDBBBBBDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3012:2219 1:N:0:GTCGCT
+AGCTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGAAAGCCTGATGCAGCAACGCCGCGTGAGTGAAGAAGTATCTCGGTATGTAAAGCTCTATCAGCAGGGAAGAAAATGACGGTACCTGACTAAGAAGCCCCGGCTAAC
++
+CCCFFFFFGHHHHJJJIJJJJGIJJJJJJJJJJCGHIJJJJJJJJJJEHHHFFFFFFEEDEEDDDDDDDDDDCDDEDDCD>ADDEDDD?B at DDEEECDDDC>CDCDDCDDDB<BBACCDCDCBB0?@CCCDCDDDDCDCCABD>@D@<CC
+ at HWI-ST1106:815:H154GADXX:1:1101:3071:2234 1:N:0:CTACGG
+AGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGACGAGAGTCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATACGGGAATAAAGTGGAGTATGCATACTCCTTTGTATGTACCGT
++
++11ADDDDDDDDDII7E=CEI@@ECB@?<?DEICEIEDEEIIIDIIDDEIEEDIIDDDDDDDD?A at A@????AA?AA5>A>?A2>9:4:13895(>:A4>A>>AAAAA>88909<(++>:::>>A(>A>:>>A>AAAAA4>ADD>BDA><
+ at HWI-ST1106:815:H154GADXX:1:1101:3245:2235 1:N:0:CCTTAA
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAAC
++
+?=?DDEFFHHHHHJGIIJIJJBFIIIIHIJIJJIJJJJJJGIIHFFFFEDEECDDDCDDDDDDDDDDDDDDDDDDDDDDCB+>ABDDDDDDDDEEEDDDDDCDDD<BDDDDDCDDDDDCDDDDD>BDCDDDDDDDDDCCDDCD5<BDBDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3136:2239 1:N:0:TTGGTA
+AGCTCCTACGGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGTAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAAC
++
+BCBFFFFFHHHHHJJJJJJJJIJJJIJJJJJJJJJJJIJJJJJHFFFFEDEEDDDDDDDDDDDDDDDDDDDDDDDDDDDDD>CDDDDDDDDDDEEEDDDDDCDDD<@DDDDDDBDDDDDDDDDDBDDDDDDDCDDDDDDDDDD at BDBBDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3036:2243 1:N:0:CAAGAA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGAGAGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATAAAGGAATAAAGTCGGGTATGGATACCCGTTTGCATGTACTTTATG
++
+:=?DDDDDHHHHHJJIJJHHFHIJJJJJJIJIJJJJJJJIJIJBHJJIJHIHFHEFEFFDCCEDDDBDDDDDDDDDDDDDDDDDDDDCBBBDEEDDDCDDDCDDEEDCDDDDDDDDCCDDD?BDDDDCEDDD at 5ACBCDCDCDDDDEDDC
+ at HWI-ST1106:815:H154GADXX:1:1101:3201:2246 1:N:0:CTGTCA
+CGCTCCTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGGCGCAGGCCTGAACCAGCCAAGTAGCGTGAAGGATGACTGCCCTATGGGTTGTAAACTTCTTTTATATGGGAATAAAGTTTTCCACGTGTGGAATTTTGTATGTACCAT
++
++1:ADDFFHHHHHIIIIIIIIHH at GHIIIGIIIIHHIIIIIIIIIIEGIIHFHFFFFEC;AAB;;CCB at BBCCCCACC@ACCCBC3:ACBCB at 0>C>CC>A at CCCCCEDDC<A>2:ACC4:ACCC:A88892?C3(+:>:<4>:4>@C at C
+ at HWI-ST1106:815:H154GADXX:1:1101:3089:2248 1:N:0:ACTTGA
+GAACCCATATGTTCTTTTCTGCAATATTCCTCGAGCCATCGTTGTGATATTGGTCAAGTCAATAAAAGCAATGACTTCTGTCAGCAATTCTTGATATCCTAGCTTATCGGCAAGCCGTCGCTGCTCTGTCAAAAACTGTCGATCATAAAT
++
+@@@DFDFDHGDHFHDBHIBHE at FDGHHEHEEFHHDGEHFHIHHIDFHGHIIIHIIIIII@@FGFHHCHGIIHCHAACBDBC at DFCCECECDE@ACEFCDDD:@:CA:CAB<<9B<?BD<B at BBDCCACCCCACCB<:A>@B?B at DDCDDE
+ at HWI-ST1106:815:H154GADXX:1:1101:3466:2192 1:N:0:CGATGT
+ATCGCGCCTTTAAGTCAGCCTGCAGGAAACAGTACGTTGACTTTAACCTCCTTTGATAATGACCAACACCATGAAGTAGATCTGGTAAACATAGCTCGATTGGGCCGTCAATGGTTTGGCGAATCATTTGAGGTTAAAAACGAACAGGAA
++
+=?+=D?DDHHGDHGFDHGHGDHIJJJIHHEGH?:??BDFAHIJJJJGI>GGHIIIH at HGA)=@HIFEFHFFFEFC;;@AEEDD at C5>CCDDDC:A at C?BCD?B?BBBBBDDA at A+>?<BDB@<BBC at AD@C?<38ACDDC<990<9?BBB
+ at HWI-ST1106:815:H154GADXX:1:1101:3490:2192 1:N:0:TAATCG
+GACTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGAGCGAAGAAGTATTTCGGGATGTAAAGCTCTATCAGCAGGGAAGAAGAAATGACGGTACCTGACTAAGAAGCACCGGCTAAAT
++
+ at 8@DDDDDFFFFFIIIIIIII;DFFIIFIF<GEFIIIIIIIIEFIIFFFFDDDDDDCBBBBBBBBB>BBBBBBBBBB:>>BDEBB&59<@ADDBBBBABBBBDBBBBB<@<?AABA?BBBBBBBBBBBBBBBBABBBBBBBBBBBBBBBB
+ at HWI-ST1106:815:H154GADXX:1:1101:3418:2203 1:N:0:TCACAA
+GACTACGGGAGGCAGCAGTGAGGAATATTGGTCAATGGTCGGCAGACTGAACCAGCCAAGTCGCGTGAGGGAAGACGGCCCTACGGGTTGTAAACCTCTTTTGTCGGAGAGTAAAGTACGCTACGTGTAGTGTATTGCAAGTATCCGAAG
++
++1=ADDDDHFFFFII=DG>EEHCHHGFDEHIH>GGHIIFGEGGGII at CEHIECHEHEE@B;ABCBBBBBAB;?BBC5<BBBBCB759>B<@CEDCCCCCC>>@?C5>@BBB4>ACC>CCBB?BBB???CC494>:B>CCC>>C>AAB?@<
+ at HWI-ST1106:815:H154GADXX:1:1101:3308:2210 1:N:0:TTGGTA
+AGCCTCGGAGGCAGCAGTGGGGGATATTGCACAATGGGGGAAACCCTGATGCAGCGACGCCGCGTGGAGGAAGAAGGTTTTCGGATTGCAAACTCCTGTCGTTAGGGACGATAATGACGGTACCTAACAAGAAAGCACCGGCTAACTACG
++
+BCCFFFFFHHHHHJJIJIGJJGFIJJJIGIGIJGIJIJJJHHHHFFFFEDEEEEDDDDBDDDDDBDDDA at BDDDDDD>CCDDDDB8<CDDDDDDDDDDCCDBBBDDDDDDDDDDCDDDDD>BDDDDDDDDDCDCDDDDDBBDDDDDDDDB
+ at HWI-ST1106:815:H154GADXX:1:1101:3481:2217 1:N:0:ATCACG
+GGGTAAAAGACTGGGCTAAGGAGAATGATTGCTGGATTGAAAATCCGGAATCATTAGGTGTGTTCTCTGACCGAGGTTCAGAGAACGAGGTTTATATGGCCTATGATGGAATACACGTTTATAAACTTTACGACTTCCGTTATTCTGACG
++
+=:8BDDEDHFG?HIFEHGIEIIGEIIFIEGCHIIIFGGIIIGGIIIGIIIGG9CGHCD83 at AEHIGIIEFH>BCAB at BCCCCC<ACBBB>08@?CD>C>8ACCCCADCCCCCCCCCCABCBCDDECCCCCC?<BBBAABAABBCDDEDCB
+ at HWI-ST1106:815:H154GADXX:1:1101:3392:2219 1:N:0:ATCACG
+GGGTACGACGCACATAACGCCCAGGGTGGAGAACTTGCCGAAATTCTTAGGTCCTACGAGGCTGATCGTAGCAGCGGCCAGAAGGACGCCGATTGTAGCCAGGCAGACTTCAACCGGATCAAGGTTGAAACCGAAAACATAAGAACCGTA
++
+B?8DDDFFHHHHHJJJJJJJJIIIIJDFGEIHIJJIIIJHHIHHHHHFFFBCDECEEDDBBDDDDDDBCBDDDCD<@B at BABDABDDBDDB>@@@ADDDDDABDDDDDCCDDDDDDBBDBDCCC>CCDDCCDBDBDDDDDDDCDCCDB?B
+ at HWI-ST1106:815:H154GADXX:1:1101:3431:2221 1:N:0:TTAGGC
+ATCGCAAATCATGGTGGGGATGATACGGCGTTTCATTGCGGAGCAGGAAATTGTTATGTTCTTATCAGGAGATTATAATTGGCCTGACAAATGGATGTGATTTATTTATTGGGCTCAATTGGGCTAGGTTGGGGATCTTCATTTGTCCAC
++
+@<BFFFFFHGHHHJCFGIIFIJIGJJJJJJIJJGIIJJJJJJHFFFFFCCEDECDDEDFEEEDCDCCDDABDDCDDEEEEDDDDDBCDDDDDDD(:@AACDDDDEDDDEDDDDBDAACCDCDDDDBDDCDDDDD0<BDCDEEEEEE at CDD
diff --git a/t/test1.fastq.gz b/t/test1.fastq.gz
new file mode 100644
index 0000000..9d409b9
Binary files /dev/null and b/t/test1.fastq.gz differ
diff --git a/t/test2.fasta b/t/test2.fasta
new file mode 100644
index 0000000..5a2ff72
--- /dev/null
+++ b/t/test2.fasta
@@ -0,0 +1,400 @@
+>HWI-ST1106:815:H154GADXX:1:1101:1244:2196 2:N:0:CTTGTA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGC
+TCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCA
+TCCTTCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:1197:2208 2:N:0:TTGGTA
+CCATTACCGCGGCGGCTGGCACGTAGTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTA
+TCTTCCCTGCTGATAGAGCTTTACATAGCGAACCACTTCTTCACTCACGCGGCGTCGCTG
+CATCAGAGTTTCCTCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:1231:2209 2:N:0:ATCACG
+CTTCTGAGCCAGTTTCTATGGCTATCTCTTGCCGCTGATGCTGATGGTGATCGCTTTGGT
+GGGTGTACTGAAAGCTACTCACTCAGAGGGAGCCGCTGCGCTCTCGGCATTGGGCATTCT
+CATTCCATACTATGTGGTGCTCTACTTATT
+>HWI-ST1106:815:H154GADXX:1:1101:1225:2231 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:1245:2247 2:N:0:ATCACG
+TAAAAAGACCTACTACTCAGTATACGCTGGATTGACAACTCACTTTTCATAGGTCTTTTA
+CTAAATAGAACTTCACAGCGGTATTTAGGTAATCGTTCTTTGAAAAGTACACATTCAACT
+ATGTTCTTATTTCCTTATAGATGTCATCTT
+>HWI-ST1106:815:H154GADXX:1:1101:1416:2204 2:N:0:GAACCT
+CCATTACCGCGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTAT
+CGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATCCC
+>HWI-ST1106:815:H154GADXX:1:1101:1397:2205 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:1258:2210 2:N:0:CAAGAA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAAC
+GGGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCTC
+>HWI-ST1106:815:H154GADXX:1:1101:1454:2212 2:N:0:TGAGGT
+CCATTACGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTT
+CTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:1323:2213 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTCT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:1432:2216 2:N:0:GACACT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTTCTTGTAAGGTACAGTCCTTCC
+TCTTCCCTTACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCATCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATCC
+>HWI-ST1106:815:H154GADXX:1:1101:1340:2224 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTAT
+CTTCCCTGCTGATAGAGCTTTACATAACGAATTACTTCTTCACTCACGCGGCGTCGCTGC
+ATCAGAGTTTCCTCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:1400:2224 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:1493:2225 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAGGTACATACAAAAC
+GGGACACGTCCCGCACTTTATTCCCTTATAAAAGAGGTTTACGATCCATAGAACCTTCAT
+CCCTCACGCGACTTGGCTGGTTCAGCCTCT
+>HWI-ST1106:815:H154GADXX:1:1101:1376:2226 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTAT
+CGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATCCC
+>HWI-ST1106:815:H154GADXX:1:1101:1296:2233 2:N:0:TCATTC
+TGTGGACTAGCAAAGCTATCCAAACTTTCATGAACCATCTCATGCCAATCAGTTGCTTTT
+CCCCTTCGTAACTGCAATTCTAGTCGCCACCATGTCGTTATTTCCGGCGGAACAATTTTA
+CGTTTTCTTTCTTGTTCCAGTTTTTTAGAT
+>HWI-ST1106:815:H154GADXX:1:1101:1467:2241 2:N:0:ATCACG
+CGCTGTTACAGATCCTGTTTACCCTGTATATGTTGATTCCAATGTCATGGCAGGAAGAAC
+AGGCACATATGACGCTCAGCGAGACCCGGTAGTTGGCTTTGAAGGGGTTGTCGTTTTCAA
+ATTCGTCCAGCAGGGAGGCATAATCCGACA
+>HWI-ST1106:815:H154GADXX:1:1101:1493:2245 2:N:0:GGCCTT
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAA
+GTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTT
+CCTGCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:1696:2195 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTAT
+CGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATCCC
+>HWI-ST1106:815:H154GADXX:1:1101:1646:2204 2:N:0:CATCTA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAAC
+GGGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCTC
+>HWI-ST1106:815:H154GADXX:1:1101:1502:2205 2:N:0:TTAGGC
+TGATTGAAGTGGGCAGTTTCATTGGCATGGCAGCCATGACCCGTAGCGAACTGACCATCA
+AGAATGTCTCCTACGAGAACTTGGGAATTATCCCCGACAGTTTCCGTCGACTAGGCATCA
+AGATGGAGCAGTGGGGAGACGACATTTACG
+>HWI-ST1106:815:H154GADXX:1:1101:1742:2207 2:N:0:CATCTA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAA
+GCCACACGTGGCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:1683:2207 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTAT
+CGTCCCTAACGACAGGAGATTACACTCCGAAAACCTTCTTCCCCCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATACC
+>HWI-ST1106:815:H154GADXX:1:1101:1541:2208 2:N:0:ATCACG
+GACTCTACCAGCATAGGAAGGTACGCCCACTATCAGCAGATCGCCATCACTTCCCAGCGA
+GACATCATCCTTCAGCACGTCTGAGGTAATGTCATACTCAATGACAGGCTTCTGAAACTG
+GGATGCTATCTCACGAACGATACGTTTGGT
+>HWI-ST1106:815:H154GADXX:1:1101:1564:2216 2:N:0:CAGATC
+CGCTTCGAGGTTTGCTTCCATGATAGAAAGATAGTTTTCTCCATTTTCTATTTGTTCATT
+CGTCAATCCTTCCAAAGGATTCAATACTTCTAAAGATACACCTGCTTCGTTTGCTAACGT
+TCTGGCAATACTATCTTTGGCGTTTTAGAT
+>HWI-ST1106:815:H154GADXX:1:1101:1719:2228 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAA
+AGGCACACGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:1844:2204 2:N:0:CACTTG
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTCCTCGTACACTACCGTCATTG
+CCAGCCATTATTCACAACCGGCACATTCGTCATGTACAACAGAGCTTTACAATCCGAAGA
+CCTTCTTCACTCACGCGGCGTTGCTCCGTC
+>HWI-ST1106:815:H154GADXX:1:1101:1890:2219 2:N:0:GCCAAT
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTA
+TCTTCCCTGCTGATAGAGCTTTACATAGCGAACTACTTCTTCACTCACGCGGCGTCGCTG
+CATCAGAGTTTCCTCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:1802:2224 2:N:0:CGTCAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTTTTCTCCAGGTACCGTCACGTC
+CTTCGTCCCTGGTAAAAGAAGTTTACAACCCGAAAGCCTTCTTCCTTCACGCGGCGTTGC
+TGGGTCAGGGTTTCCCCCATTGCCCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:1840:2224 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACG
+GGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGGCCAT
+>HWI-ST1106:815:H154GADXX:1:1101:1923:2228 2:N:0:AAGCGA
+CCATTACTGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:1769:2229 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGC
+TCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCA
+TCCTTCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:1997:2231 2:N:0:TAGAAG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTAT
+CTTCCCTGCTGATAGAGCTTTACATAGCGAACTACTTCTTCACTCACGCGGCGTCGCTGC
+ATCAGAGTTTCGTCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:1965:2235 2:N:0:CCACTC
+GCTGCGTTCTTCATCGATGCCGGAACCAAGAGATCCGTTGTTGAAAGTTTTAATTATTGT
+TTAACTAAAAACTCAGACTGCAAACTTCAGACAGTGTTCAAATGTTAGTCTTCGGCGGGC
+CGTGGCCACGCCGAAGCAACAGGGTACAGA
+>HWI-ST1106:815:H154GADXX:1:1101:1871:2243 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAA
+AGGCACACGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:2118:2199 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTAT
+CTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGC
+ATCAGGGTTTCCCCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:2145:2206 2:N:0:CTATGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTCT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:2188:2208 2:N:0:TGACCA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTATTCGCCAGGTACCGTCTTCT
+ACTCGTCCCCGACAAAAGAAGTTTACAACCCGAAAGCCTTCTTCCTTCACGCGGCGTTGC
+TGGGTCAGGCTTGCGCCCATTGCCCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:2116:2218 2:N:0:GAACCT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTAT
+CGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGC
+ATCAGGGTTCCCCCCATTGTGCAATATCCC
+>HWI-ST1106:815:H154GADXX:1:1101:2046:2228 2:N:0:TTAGGC
+TTCAGGTCATAACTTTTGATCTTGCAGGCATCGCCGGAATTTCCCTCCACGGTATAAACA
+CGGCTGCCATCGGTGCCGACAACAATTCCCACATGGTCTGCGGAACCATCCAGATCCCAA
+TCGAAGAAAATGGCATCACCGGGAGCGATG
+>HWI-ST1106:815:H154GADXX:1:1101:2092:2229 2:N:0:AGTCAA
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAA
+AGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCA
+TCCTGCACGCTACTTGGCTGGTTCAGGCTC
+>HWI-ST1106:815:H154GADXX:1:1101:2195:2237 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAATCAGGTACCGTCACTA
+TCTTCCCTGCTGATAGAGCTTTACATAACGAATTACTTCTTCACTCACGCGCCGTCGCGG
+CATCAGAGTTTCTTCCATTTTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:2147:2238 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTAT
+CTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGC
+ATCAGGCTTTCGCCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:2498:2195 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATAATACATACAAAA
+CAGTATACATACTGCACTTTATTCTTATATAAAAGAAGTTTACGACCCATAGAGCCTTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCTA
+>HWI-ST1106:815:H154GADXX:1:1101:2263:2198 2:N:0:ACTTGA
+TTCTACAGCGTCTTTCAAGAAACGACCAAGTGTTCGATAATCATGGTGCAAAATTTCACC
+TACACGGTTACGACTAGCCATTGTTCCGATGTTCACACGTGTGCCGGGGAAACCTTTGAT
+ATTGTTGAAAGTCATAGCTGGTCCTTCTTG
+>HWI-ST1106:815:H154GADXX:1:1101:2307:2201 2:N:0:TGGATT
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTAT
+CTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGC
+ATCAGGCTTTCGCCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:2283:2204 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAA
+TGGTATGCATACCAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCCGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCTC
+>HWI-ST1106:815:H154GADXX:1:1101:2453:2206 2:N:0:ATACAC
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAA
+AGTCTCACGAGACTAACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCT
+TCCTGCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:2336:2209 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATTATACATACAAAA
+CAGTATACATACTGCACTTTATTCTAATATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCCA
+>HWI-ST1106:815:H154GADXX:1:1101:2378:2210 2:N:0:CTACGG
+GCTTCCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGG
+GTATACATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATC
+CTTCACGCTACTTGGCTGGTTCAGGCCTGC
+>HWI-ST1106:815:H154GADXX:1:1101:2470:2220 2:N:0:ATCACG
+AAATTGACGAAATAAACCACCAGCTGACCGAAGATGATGGCAAACTGGTTCCAGCTGACC
+AACATACCACGGATGTTACTAGGCGCAATCTCACCGATATACATCGGACATACAGCAGAT
+GCCAGACCCACACCGATACCGCCAATCACA
+>HWI-ST1106:815:H154GADXX:1:1101:2434:2220 2:N:0:CGATGT
+TAGGCTGAGTCCATCCTGGATCATTTGTAGTTTCTTCAGAAAGTATATCTTTTCCCTGAG
+TAGCAATATTAGCATGTTCTCCCTTTTCTATTTTATGCTTGTCAGGAATACCAGTATAAG
+TTAATGTATGAAGCACTCGAATATATGATT
+>HWI-ST1106:815:H154GADXX:1:1101:2285:2223 2:N:0:CGAATA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAA
+GCCACACGTGGCTAACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2390:2234 2:N:0:ATACAC
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTT
+TCTTTCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTTGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:2331:2236 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTATTCTACAGGTACTGTCTTGTT
+TCTTCCCTGTCTAAAGCAGTTTACAATCCGAAAACCTTCTTCCTGCACGCGGCGTCACTG
+CGTCAGAGTTTCCTCCATTGCGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:2413:2237 2:N:0:CAGATC
+TACATCTCTTCTCTCCTAATGTTAGTTTTAGAAATAAAGACAGAATCTGCGACCTTCAAT
+CTCACAAATTCGTATGTCCATTTCGTACAATTCGTCCAGTACATCTTTTTTTATCATTTC
+TTGGGTCGTTCCTTGCGTGAATAACTGCCC
+>HWI-ST1106:815:H154GADXX:1:1101:2368:2242 2:N:0:TCCTCA
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:2491:2246 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTTCTTGAAAGGTACCGTCAGAAC
+TGTATCATTTCCTATACAGTTTGTTCTTCCCTAACAACAGAAGTTTACAATCCAAAGGAC
+CGTCATCCTTCACGCGGCATTGCTCGTTCA
+>HWI-ST1106:815:H154GADXX:1:1101:2525:2193 2:N:0:CAGATC
+TTCTGAATAAAGGGAAACTTGTGCACTGACAGTAGAAGCCCCAGAGATATTTTTTTGCTG
+TTTGATCAATTCTAATGCACTGTTAAAACATGCACTGAAACCAGCTGCAAACAATTGTTC
+AGGGTTGGTTGCATTTTCGACGCGTTTACC
+>HWI-ST1106:815:H154GADXX:1:1101:2680:2193 2:N:0:GAACCT
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAA
+GTCTCACGAGACTAACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTT
+CCTGCACGCTACTTGGCTGGTTCAGGCTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2516:2210 2:N:0:TAGCTT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAAT
+TCCACACGTGGAAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2713:2212 2:N:0:TGACCA
+AGATTGCCACCTCCGTTGATATTATATGTCACTATTCCATTATTGGGACCACTAAACTTT
+ATTAAGGAAGAAGAACCTGAACAAATTGGACTAGCGCCATTAATTGAAATTGTAGCCGTT
+GGTGTTGAACGAACTGTTACAGCTGCGCTA
+>HWI-ST1106:815:H154GADXX:1:1101:2678:2222 2:N:0:CGCTGA
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAA
+ATCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCAT
+CCTGCACGCTACTTGGCTGGTTCAGGCTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2588:2225 2:N:0:CCTTCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAAC
+GGGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGGCCA
+>HWI-ST1106:815:H154GADXX:1:1101:2713:2231 2:N:0:TGACCA
+AGATTGCCACCTCCGTTGATATTATATGTCACTATTCCATTATTGGGACCACTAAACTTT
+ATTAAGGAAGAAGAACCTGAACAAATTGGACTAGCGCCATTAATTGAAATTGTAGCCGTT
+GGTGTTGAACGAACTGTTACAGCTGCGCTA
+>HWI-ST1106:815:H154GADXX:1:1101:2557:2232 2:N:0:CAAGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACG
+GGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGATCAGGCTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2740:2237 2:N:0:AGTTCC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:2527:2244 2:N:0:GTTGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAA
+GGCACGCGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:2603:2248 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGATGCTTATTCCTTAGCTACCGTCACTGT
+CTTCGTCACTAAGAAAAGAAGTTTACAATCCGAAAACCGTCATCCTTCACGCGGCGTTGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:2853:2195 2:N:0:ACTTGA
+AACTATAACTCTTTCCAGGAACTAAATGAAAATCCTATTTTCGCAGATGTTAGCGTATAC
+AATCGTACAGTCATGACACCACAAAGTCTTCCGCATGTAGTAGATGAAGCCATTAAAGCC
+GCCTATGAGCATAAAGGCGTGGCTATCGTG
+>HWI-ST1106:815:H154GADXX:1:1101:2884:2198 2:N:0:TGGATT
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAA
+AGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCT
+TCCTGCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:2751:2204 2:N:0:AAGCTT
+GCTGCGTTCTTCATCGATGCCGGAACCAAGAGATCCGTTGTTGAAAGTTTTAAATAATTT
+ATATTTTCACTCAGACTTCAATCTTCAGACAGAGTTCGGGGGTGTCTTCGGCGGGCGCGG
+GCCCGGGGGCGTGAGCCCCCCGGCGGCCAG
+>HWI-ST1106:815:H154GADXX:1:1101:2785:2207 2:N:0:AAGAAG
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCCTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:2938:2209 2:N:0:CAGATC
+CCAAGAAGGAATCGATTATTTGGCAGGCCTGCCGGATAGCCATCCAAAGGTCTTGATAGT
+AAAAGAAGGAAGATATGATGAATATATAGAAAGCAGATTATCCAATTTTAAACTTGTGGG
+AGCAGGAACAGTAGTTATCTCCGGTAATCG
+>HWI-ST1106:815:H154GADXX:1:1101:2969:2210 2:N:0:CGTCAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACG
+GGTATACATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGGCCTG
+>HWI-ST1106:815:H154GADXX:1:1101:2909:2214 2:N:0:CCGTCC
+TTATCAAAACTTATCTTATTTTCGAAGTAAAAGTTGAAGCTTTGATGGGGTAAATATAAA
+AATATATTTCAGATTTTTATTTTTTAAAAACAAATAAAAGTAAAGAATTTCAACTACAAG
+GTTGTAGTAATGAATAAATTAACAAATAAA
+>HWI-ST1106:815:H154GADXX:1:1101:2888:2222 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTT
+CTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTTGCTGC
+ATCAGGCTTTCGCCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:2873:2233 2:N:0:ACTTGA
+TCTGCAAGCACTGGTCCTTTGGCTAGTTCTGCTTGTCCCTTTGTTTCTTCATTTAAATGA
+ACCGTTCCAGATACAGGAGCTTTTAGTATTCCTTTTGAAAGTTGATCGTCCAAACTTTTG
+ATAACTGACTGGTTCTTCTCTTGTTTTTCA
+>HWI-ST1106:815:H154GADXX:1:1101:2990:2243 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTG
+CATCAGAGTTTCCTCCATTGTGCAATATCC
+>HWI-ST1106:815:H154GADXX:1:1101:2791:2243 2:N:0:CAGATC
+ATTTCTCAATCTTTTCTCTCCGTTGGGATAACAACGATTATGTGGGTATTTGGTGGATTC
+GGATTGGCCTTTGGACGGGATATCGGCGGTGTTATTTGTAAACCGGCGGGTTTTTTTTTG
+TTGAGGCATGTTACAAGCTTCCCCAACACG
+>HWI-ST1106:815:H154GADXX:1:1101:3046:2196 2:N:0:AGTTCC
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAA
+ATCCACACGTGGATAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCA
+TCCTTCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:3147:2203 2:N:0:GGCCTT
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTGT
+CTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTGC
+ATCAGAGTTTCCTCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:3211:2211 2:N:0:AGTGGT
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTGCATGCAAAA
+AGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCT
+TCCTGCACGCTACTTGGCTGGTTCAGACTC
+>HWI-ST1106:815:H154GADXX:1:1101:3127:2215 2:N:0:ATCACG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTAT
+CTTCCCTGCTGATAGAGCGTTACATAACGAATTACTTCTTCACTCACGCGGCGTCGCTGC
+ATCAGAGTTTCCTCCATTGTGCAATATTCC
+>HWI-ST1106:815:H154GADXX:1:1101:3233:2216 2:N:0:TTGGTA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTTCTGGTTAGATACCGTCAAGGC
+GCTAACAGTTACTCTAGCACTTGTTCTTCTCTAACAACAGAGTTTTACGATCCGAAAACC
+TTCTTCACTCACGCGGCGTTGCTCCGTCAG
+>HWI-ST1106:815:H154GADXX:1:1101:3185:2216 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTTGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:3012:2219 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTT
+TCTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTTGCTG
+CATCAGGCTTTCGCCCATTGTGCAATATTC
+>HWI-ST1106:815:H154GADXX:1:1101:3071:2234 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAGG
+AGTATGCATACTCCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGACTCT
+>HWI-ST1106:815:H154GADXX:1:1101:3245:2235 2:N:0:CCTTAA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTA
+TCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATCC
+>HWI-ST1106:815:H154GADXX:1:1101:3136:2239 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTA
+TCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATCC
+>HWI-ST1106:815:H154GADXX:1:1101:3036:2243 2:N:0:CAAGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACG
+GGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGGCTCT
+>HWI-ST1106:815:H154GADXX:1:1101:3201:2246 2:N:0:CTGTCA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAAT
+TCCACACGTGGAAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCAT
+CCTTCACGCTACTTGGCTGGTTCAGGCCTG
+>HWI-ST1106:815:H154GADXX:1:1101:3089:2248 2:N:0:ACTTGA
+TCATACGCAAGTTTCAAATGAACTTCCTGAAAGCATTATGGACAGTATACGAGAAGTACG
+TGATTATTTTGAAGAGTCTACCATTCTTCAGGGAATTGACGTGATTTATGATCGACAGTT
+TTTGACAGAGCAGCGACGGCTTGCCGATAA
+>HWI-ST1106:815:H154GADXX:1:1101:3466:2192 2:N:0:CGATGT
+AAAACAAATTCAGTTTCTGAATTGTTATTCAGCGCAGGAAACGAGATGTTTCCGACTAAA
+ATTCCGTTTGCGGTCACAGTAAGTGAGGTAGGTGTAAAAGCTGCTGAGGCGGCTGTCAGC
+ATAATTTTAACGGTTGATGTGGCGTCAAAA
+>HWI-ST1106:815:H154GADXX:1:1101:3490:2192 2:N:0:TAATCG
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTT
+CTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGC
+TGCATCAGGGTTTCCCCCATTGTGCAATAT
+>HWI-ST1106:815:H154GADXX:1:1101:3418:2203 2:N:0:TCACAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTTTTCTTCGGATACTTGCAATAC
+ACTACACGTAGCGTACTTTACTCTCCGACAAAAGAGGTTTACAACCCGTAGGGCCGTCTT
+CCCTCACGCGACTTGGCTGGTTCAGTCTGC
+>HWI-ST1106:815:H154GADXX:1:1101:3308:2210 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTA
+TCGTCCCTAACGACAGGAGTTTGCAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTG
+CATCAGGGTTTCCCCCATTGTGCAATATCC
+>HWI-ST1106:815:H154GADXX:1:1101:3481:2217 2:N:0:ATCACG
+CGATTCTGCGAGAAACCGATGAGATCGTAGGGGCATGCTGTGAAGTATTGGTTGTGAGCA
+ACAATTCGTTCAAAGAAAGGAGTAAGGTTGTCGTCAGAATAACGGAAGTCGTAAAGTTTA
+TAAACGTGTATTCCATCATAGGCCATATAA
+>HWI-ST1106:815:H154GADXX:1:1101:3392:2219 2:N:0:ATCACG
+ATGGGCGGTTACGCAGAATACCGCTTCGGGAGAGCCGGCAATTTCCTCTCCAACTTCTGC
+TACACGATTTCTCTGATCATCGCCAACGTTGCTATTGCAAGCGGCGTTGTCAGCTACGGT
+TCTTATGTTTTCGGTTTCAACCTTGATCCG
+>HWI-ST1106:815:H154GADXX:1:1101:3431:2221 2:N:0:TTAGGC
+ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATG
+CATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCA
+CGACTAATGATAATGGCAAAGTATTTGAAG
diff --git a/t/test2.fastq b/t/test2.fastq
new file mode 100644
index 0000000..5e4944c
--- /dev/null
+++ b/t/test2.fastq
@@ -0,0 +1,400 @@
+ at HWI-ST1106:815:H154GADXX:1:1101:1244:2196 2:N:0:CTTGTA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC
++
+=+=+<?7@?C0CACAABABABBAA=:<AABBBAAAAABBAABBBBAAAAA;?@>>75>>=@>?======;9;=8255+88=:?????????=::=;<?8883::8;8;;=;<=??7<????3;?????8;===??????###########
+ at HWI-ST1106:815:H154GADXX:1:1101:1197:2208 2:N:0:TTGGTA
+CCATTACCGCGGCGGCTGGCACGTAGTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCTTTACATAGCGAACCACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATTC
++
+?:=BDDDBFDDFA)?;7AFEIII?=?ED7?@)9/3>?BB at AA@ABADBB9 at A>BBBBBBBBBBDEBBBA?@B>BBA>ABBBBBBBBDBBBBB>BBBBBABBB@>A>BBBBBBBBBBB9><BABBBBBBBAADBABB@>BBDBBDBBBBDE
+ at HWI-ST1106:815:H154GADXX:1:1101:1231:2209 2:N:0:ATCACG
+CTTCTGAGCCAGTTTCTATGGCTATCTCTTGCCGCTGATGCTGATGGTGATCGCTTTGGTGGGTGTACTGAAAGCTACTCACTCAGAGGGAGCCGCTGCGCTCTCGGCATTGGGCATTCTCATTCCATACTATGTGGTGCTCTACTTATT
++
+@@@D+=BBBFAFCG at GFFEHEIA<ACHHCFHIIEB at FFGFFIIFIEFFGFCIDFFFFGF6@DFEB=BDDD>@ACAC at CBBBBBBBBB>?BBBBBBBBB at B><>BB5?B at BABBBBBBBBEBDDEDEDB>?BB at ABBB9?:::@AA>B>AD
+ at HWI-ST1106:815:H154GADXX:1:1101:1225:2231 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATTC
++
+@@@BDD>DFD at FFH@GHGG1DGHFHGHHGGCHGGFGHHCE?DDDECE6>@@A>;?BBBEDCACCCCCCCBCCCCCCCCCCACCCCEE at CBBBBB:ACCCCCCECCC9AAB9>BBBBBBBBBCCCC:@13<8 at CCCB@CCCECCDACC>@C
+ at HWI-ST1106:815:H154GADXX:1:1101:1245:2247 2:N:0:ATCACG
+TAAAAAGACCTACTACTCAGTATACGCTGGATTGACAACTCACTTTTCATAGGTCTTTTACTAAATAGAACTTCACAGCGGTATTTAGGTAATCGTTCTTTGAAAAGTACACATTCAACTATGTTCTTATTTCCTTATAGATGTCATCTT
++
+@?@DFFADHGFHHIJJJJJIHIJIJJIIJJIJIIIJJIIGIIJEHII@@FIEGF:CHIJJIIJJJJJDGHGJJJFHHGDFCACDEDDCCCDDEDDBDDDCCCCDCCDDDACCDDCDC>ADDCCAC>CC3>@@>>>CDA at AACCDDABAAA
+ at HWI-ST1106:815:H154GADXX:1:1101:1416:2204 2:N:0:GAACCT
+CCATTACCGCGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCCC
++
+@@?DFFFBDFHHFHIGIIJJIHHGFHJIFHIJJDFFHIJJIJJHIIIIHIJJEHH7BEDDDDEDDDA at CAB<@BBB<?(9>>C at CC?AB0?BB>?CDDCDDC at CCDCB<9@<>5>B at 9B<ACCDCCB3AB at CACB@CDCC4:ACCD@:@C
+ at HWI-ST1106:815:H154GADXX:1:1101:1397:2205 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+===AAAAAAAA8A)1:7?AA>*:00=AB<?B<A:-5<BABBBABBBAA>=AA;=@@@@>@B(;?>?=?:=>=>?:;>???????????=?===;;=????????=5;89:<======;;=;==??:?::;(8;??;8;9<=7:????::;
+ at HWI-ST1106:815:H154GADXX:1:1101:1258:2210 2:N:0:CAAGAA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCTC
++
+@?BDFFFFHHGHHJJIJJJJJJIIGHFHGHJJIJJIJJIJIHHHHHHHFCDFFFFEEEEEDDB8?CCDDDCDDDDDDDDDDDDEECDDDDEEEDDDDDACD>ACD>BDDDDDDBDDDDDDEDDDDDDDDCDDDDDDDCDDB<@CCDDCBD
+ at HWI-ST1106:815:H154GADXX:1:1101:1454:2212 2:N:0:TGAGGT
+CCATTACGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATTCC
++
+CCCFFFFFHHHHHIJJIIJJJJBFHHGIIIJJGHEHHHFEFFEFFFEEEEEE?BD=ADFE at C>@CCDDACDCACCA at CDDDDDDDDCCBBDBD>CD at CDDDECDDDDDDBD@BDDDDBBBDDDCCAB+<<>C4<5>CDDCCCDDC3>C@>
+ at HWI-ST1106:815:H154GADXX:1:1101:1323:2213 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATTC
++
+???DDD?DD at DD:@CEB>D9?@0BDEEDEEEIIDADEICEIIICICDDDD>A@??@@DADE>A>>A9;>?>AAAAAAAAAAAAAADEA??>>;>>>AAA>A:29>8>A?>?>7>??>>??>AAAAAA?+8<A::<9>?A<:AAD>AAAB>
+ at HWI-ST1106:815:H154GADXX:1:1101:1432:2216 2:N:0:GACACT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTTCTTGTAAGGTACAGTCCTTCCTCTTCCCTTACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCATCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCC
++
+CCCFFDDFHGHHDGIJEEHIJIGHJHIIJJIJJFHIIJJAHHHHHHHFFFFFCCC:@C>;;;>C:ACAC::85380?B at ACCCDCCC399@?BDA0>CCDAA@:@(9??@@90553<?ABBCAA@@CB<A at D>@C>DCA at ACAC@ACCDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1340:2224 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCTTTACATAACGAATTACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATTCC
++
+@@@FFFFFHHHHHIGJJJFIJJHGHJIIIJJJJIIJJJJJJJHGHHHHHFFFFDDDDDDDDDEEDDDDDDCDDDDDDDADDCDDEEDDDDDDDDDDDDDDCCCCDCDDDDDDDDDDDDDDDDCDDAC>ACDDDDDDDDDDDDEDDCDEDE
+ at HWI-ST1106:815:H154GADXX:1:1101:1400:2224 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+@@@DDDDDHDFHFAGGIIIIIGII;DHIAFHGIGFHGHIIIIGHIIFHHHFHCBECCCEEEEFCCFCACCCBCCCCCCACCCCCCCCDECCBBBBACCCCCCCCB at BBBCBABBBBBBBBBBBCCACCAB3<@CCCABBCC at ACCEC@>C
+ at HWI-ST1106:815:H154GADXX:1:1101:1493:2225 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAGGTACATACAAAACGGGACACGTCCCGCACTTTATTCCCTTATAAAAGAGGTTTACGATCCATAGAACCTTCATCCCTCACGCGACTTGGCTGGTTCAGCCTCT
++
+ at 7?DDFFFHHGGHIIGIBHHIIIBFHIIIIIIIGIGIIIIIHFHHHGGCDFFFFEEEECBBB>@BBCCBB?@BBBCCCCCCCEDCCCCCCCDCC09A at BCC@BBB?BCCCC at CC?CCCCDDCCCCBBCBCCCBCCCCCCBCCCCC:C?CC
+ at HWI-ST1106:815:H154GADXX:1:1101:1376:2226 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCCC
++
+@@@FFFFFFHHHHIIIJJHIJJFHHJJIIIIJJ at FBHJIJHJJIHHHGEHFFFFDCCDEEDDDDDDDDDDB@BBDDDDCDCDCDDDDDDBDDDDDDDDDDDDACCDCDDDDDDDDDDDDDDDDDDDDDD at CACDBDDDDEDCECCCCC>C
+ at HWI-ST1106:815:H154GADXX:1:1101:1296:2233 2:N:0:TCATTC
+TGTGGACTAGCAAAGCTATCCAAACTTTCATGAACCATCTCATGCCAATCAGTTGCTTTTCCCCTTCGTAACTGCAATTCTAGTCGCCACCATGTCGTTATTTCCGGCGGAACAATTTTACGTTTTCTTTCTTGTTCCAGTTTTTTAGAT
++
+??@DFE8DH>FBHEAFHGJGGHHIHHHIJIIHIGGGIGGGIIIJIIIIFFFGGGGGHEJI:=BFDHGEHIIJGHGFHH at CDD;??>CCDDBBDCEDDD:?9>ACD<>BBD at BBB9CC3>@CD?39B3+>CCCCDCCC>@CCDCD?@DDDC
+ at HWI-ST1106:815:H154GADXX:1:1101:1467:2241 2:N:0:ATCACG
+CGCTGTTACAGATCCTGTTTACCCTGTATATGTTGATTCCAATGTCATGGCAGGAAGAACAGGCACATATGACGCTCAGCGAGACCCGGTAGTTGGCTTTGAAGGGGTTGTCGTTTTCAAATTCGTCCAGCAGGGAGGCATAATCCGACA
++
+ at B@BA at DDHFDHHCHGIHHHHH@FDGAFHIIIFHIJIHGJ@>GHDGGGHBGGGBEGIFHIGFEAGHJCA=EHJFGA8=BEBDDBBBDBB8<>:>@C(4<CCDD at CBB)5<9@@8>@BCCCCCCC?>?<?@CCBDBB5@?<AACCCD>?>>
+ at HWI-ST1106:815:H154GADXX:1:1101:1493:2245 2:N:0:GGCCTT
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTTCCTGCACGCTACTTGGCTGGTTCAGACTCT
++
+@@@FFDDFGHHHHGIJJEIIJHEHGJIIHIGJJJJJJJJJHHHHHGGFEFFFFFEEEEEDDCDEDEDDDDDDDDDDDDDDDDDDDDDDDDEEDDDDDDDEECDCDBDDCDCCBDDDDBDDDCCDDDCDDDDDDDDDDDDBCCCDDDCCCD
+ at HWI-ST1106:815:H154GADXX:1:1101:1696:2195 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCCC
++
+;@@DDDDDAFFA at 81CCFFFED:090B<0/B at F<5A at DEEDDA=AEC?7=?BBD9=@DDDBB=??@BBBBBBBBBB@@?BBDBBBB??BBBBBBBBBBBBB>@ABBBB at BBBBBBB9BBBBBBBB>?+2<A at BBBB@@BDBB@>AA:BDB
+ at HWI-ST1106:815:H154GADXX:1:1101:1646:2204 2:N:0:CATCTA
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCTC
++
+@@@DD>BDHH:<F:EHC?DAGGF@:D/?8B?F6;FAEDGHACHHHDHF?DDDBCECCCCABBB;?CCCDD@>CCBB>BBCCCCDDCCCCCEECCC@@C:@C::AC>?BBCC>A at C@BCCCDCCCCCC>?B<BBCACC>A053:ACCCCBB
+ at HWI-ST1106:815:H154GADXX:1:1101:1502:2205 2:N:0:TTAGGC
+TGATTGAAGTGGGCAGTTTCATTGGCATGGCAGCCATGACCCGTAGCGAACTGACCATCAAGAATGTCTCCTACGAGAACTTGGGAATTATCCCCGACAGTTTCCGTCGACTAGGCATCAAGATGGAGCAGTGGGGAGACGACATTTACG
++
+;=?D7:BD?:C<FD:CCG@?<FHBF<ACFGFIEAF;FGF>BF:?DBBD;AE at DAE;D@?)7?;@;77?BCC3;>83>8;:@>>59,:5>B::(489>5>B(+++(+489@<?&399>49>(+:@>A>BB@####################
+ at HWI-ST1106:815:H154GADXX:1:1101:1742:2207 2:N:0:CATCTA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAAGCCACACGTGGCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTCT
++
+<@@DD;??@<F at DGBEHICHEFB@DIGHCGIIIIGIIIGGIECHHFEDCDCCD;>ACCBBB?<CC?8=?A at BBCCCCCACCC:@A>BBBCEDCC?A>@A:@@@C>?>BCCCCBC@>?>:>4 at CCCCCB?BBBCCCCCCBBC>@:>3(:>C
+ at HWI-ST1106:815:H154GADXX:1:1101:1683:2207 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGATTACACTCCGAAAACCTTCTTCCCCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATACC
++
+?@@FDFFFHHGHHIJJJJJJJJDGEHJJIJJJJFHIJJB at EEG7=EEHEHFFFFDD;C@;@=(55;@((5??39<((((+:@>A(((9<&+5992>4>@:>:(+0&95 at D@BB95><9959:>C>4?98<C(:(553+:ACD at 4>>C###
+ at HWI-ST1106:815:H154GADXX:1:1101:1541:2208 2:N:0:ATCACG
+GACTCTACCAGCATAGGAAGGTACGCCCACTATCAGCAGATCGCCATCACTTCCCAGCGAGACATCATCCTTCAGCACGTCTGAGGTAATGTCATACTCAATGACAGGCTTCTGAAACTGGGATGCTATCTCACGAACGATACGTTTGGT
++
+?;?DDD:AC<CDD<EEEEF>;+<FFDFEADDDD<@?BD at DEEBD@DBBBBCIDCC=AAA@'-=@ADDAFAABAAAA5=99??8>>8::A>A>DE(>AAAAA>A>A>3208>>A3:>A>A:><>A??A3>>AAAA>>>>3><89<4<<<<>
+ at HWI-ST1106:815:H154GADXX:1:1101:1564:2216 2:N:0:CAGATC
+CGCTTCGAGGTTTGCTTCCATGATAGAAAGATAGTTTTCTCCATTTTCTATTTGTTCATTCGTCAATCCTTCCAAAGGATTCAATACTTCTAAAGATACACCTGCTTCGTTTGCTAACGTTCTGGCAATACTATCTTTGGCGTTTTAGAT
++
+@<@B==D;;8 at A?ACF?AACB at CBH?+?FHBGGHHICHC*:*:?FFGGF9DB?DDDD?FE<B8;FFD;;CG)@=DEAE(7);;)77;>A;@66>@@A@>;A55>5:>:;9(883>>C9<+<(<:>AC(9A at C3>ACDCC>C><B><A34:
+ at HWI-ST1106:815:H154GADXX:1:1101:1719:2228 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAAGGCACACGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTC
++
+@@@DABDDAFHDFHGHIIG8CFDAGIBBDFIGHIGIGIIIIFFEEHHHEDD8 at CCCCCCBBBB??95<8 at 8?8:3+8AC>CCCDEC at 858@CDCABBCCC>>:@ACB><9>CCBCBB<9ACC at C:(+:2<5(5CCC>9ABBCC@@>4:>>
+ at HWI-ST1106:815:H154GADXX:1:1101:1844:2204 2:N:0:CACTTG
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTCCTCGTACACTACCGTCATTGCCAGCCATTATTCACAACCGGCACATTCGTCATGTACAACAGAGCTTTACAATCCGAAGACCTTCTTCACTCACGCGGCGTTGCTCCGTC
++
+C at CFFFFEFHGFHHHJJJEIIJGHGIHIJJJJJJJJJJIIGGHIHHHFDFFEEDDDDD@CCDCABB<:ACADEDDDD at D@BDDDDDDCECDDBDDDDDDDD<CACCCCCCCCCDDDDBD>CDDDDCCC>CACCCBB at BDD><B>A at C><A
+ at HWI-ST1106:815:H154GADXX:1:1101:1890:2219 2:N:0:GCCAAT
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCTTTACATAGCGAACTACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATTC
++
+ at CCFFFFDHHHHFGGHJGGIIIIIJGIJJIBHIGBHIIHIHIIHHHHHHFDFFFDDDDDDCDDDEDDDD@CDDDDDDDCCDDDDDDDCCDBDDDDDDDCCCCCCDCCDDDDBDDBDDDDDDDDDDDCDCDDEDCDDDACDCDDECDDDED
+ at HWI-ST1106:815:H154GADXX:1:1101:1802:2224 2:N:0:CGTCAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTTTTCTCCAGGTACCGTCACGTCCTTCGTCCCTGGTAAAAGAAGTTTACAACCCGAAAGCCTTCTTCCTTCACGCGGCGTTGCTGGGTCAGGGTTTCCCCCATTGCCCAATAT
++
+@@?DDBDDAFF:@E;EGIEFGI8F>GHG@@HHGIGEGHIGIGI>EA?EAE>B<59AA>B at BBCCBCBBBCCBC(::>C8(+:>@DCCACBBB<<><?BCCA:@C:>CCCCBBBBBBB9@@>A38?CBCCB38?>CCCB<CCC at 3>@@CAC
+ at HWI-ST1106:815:H154GADXX:1:1101:1840:2224 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCAT
++
+@@@FFFFFGHHGHIGJIJJJJJIFHBHGGIJIGIIIJJJJJHHHHHHHDDFFFFFEEEEDDD>@DDDEEDDCCDDDDDDDDDDEDDDDDEEECDBDDDDECCCDC?BDDDDCDDDDDDDDDDDDDDCDBDDDDDDDDDBBACCDDCDBDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1923:2228 2:N:0:AAGCGA
+CCATTACTGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+ at CCFDFFFHGHHHJJIIHJIJJGEGGIJJJHIIJIHGIIJIJJIJIJJJIDDGGHFHHHFFFFFFFACCCEDDC@CDDACCDDCDDDDCCCBDBBBCDDDCCCCBBDDDDDBBDDDDDBDDBDCDDCDCA+2<:>>AB<AA@>CCDC@>A
+ at HWI-ST1106:815:H154GADXX:1:1101:1769:2229 2:N:0:TTAGGC
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTATTCATAAGGTACATACAAGCTCCCACACGTGGGAGGGTTTATTCCCTTATAAAAGAAGTTTACAATCCGTAGGACCTTCATCCTTCACGCTACTTGGCTGGTTCAGACTC
++
+CCCFFEFFHHGHHIIJIJJJJJJJGJIIGJJJJIEHIJHJIJJHHHHHGHCFFFFEEEEDEDDDDBDDDBBDDDDDB+<@ADDCDCDDCDACDDDB<C>CD>@ACCCCDBD?BCAACCCDEDCCCDDDDBDDDCDCDDCBD?@CCCDDCD
+ at HWI-ST1106:815:H154GADXX:1:1101:1997:2231 2:N:0:TAGAAG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCTTTACATAGCGAACTACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCGTCCATTGTGCAATATTCC
++
+B at CFDFFFHHFHGIJJJJJJJIGHJJJJIIIJJ0@FHICGIJHHHHHGHDCFFCDD(>CDDDEEDDDDDDDDDDDDDDDDDDDDEE:AB>D9ACDDDDDDD3>CDCCDDDDDDDDDDDDDDDDDD:4 at CDE08@@DEEDDDDEDDCDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:1965:2235 2:N:0:CCACTC
+GCTGCGTTCTTCATCGATGCCGGAACCAAGAGATCCGTTGTTGAAAGTTTTAATTATTGTTTAACTAAAAACTCAGACTGCAAACTTCAGACAGTGTTCAAATGTTAGTCTTCGGCGGGCCGTGGCCACGCCGAAGCAACAGGGTACAGA
++
+@@@DF<?DHHHHDIIJJJJIJJIJGHGIGIIIIIJJJIHIFFGIIJJGGHIEGIJIJIG?EFFCDEFFFDACEEDDDDDDDDCDDDDDDCDDDDDCDDCDD>>@BCCCC at CDDABDB9@>B at BB@>A?<>BB<<930>C?A8<???@>@>
+ at HWI-ST1106:815:H154GADXX:1:1101:1871:2243 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAAGGCACACGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTC
++
+??@DDEFFHHGHHHIGIIIIJJJJHHIGIIIJJGIHIIIJFHHHHHHHDDDDEEEDEDDDDDDDDDDDDBDDDDDDDACDDDDEEDBDDDDEECDBDD@>>:ACCC<<BDDDDBCDDCDDECDDDDDDDDDDDDCCDDDDDCCDCCDDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2118:2199 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTATCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATTCC
++
+CCCFFFFFHHFHHJJJJJJJIJHHIJJIIIJJJJIJHHCCECDDDFEEEECEDDDDDEEEDCFEDDD:2+>C4 at A3::CDCCDD@>CDDDDD@(>CDDDDDA55?BCDDDDDDDDDDDDDDDDDDDDCBDDDDDDDDDDEDDECCCDCDE
+ at HWI-ST1106:815:H154GADXX:1:1101:2145:2206 2:N:0:CTATGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATTC
++
+@@@FDFFFHHGHHJJJIJJJJJ:DHHJJJJJJGIEIJJEIJJGIIFEEHHHFF?BDEDEA>>CDDDDDCBDDDCCDACDACCDDDDECCDDDB at DD@CDCD@?@DBDDBBDDDBBDBDDBBDDDDCA?3<<CC@<9 at CCDDCDD:A at CED
+ at HWI-ST1106:815:H154GADXX:1:1101:2188:2208 2:N:0:TGACCA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTATTCGCCAGGTACCGTCTTCTACTCGTCCCCGACAAAAGAAGTTTACAACCCGAAAGCCTTCTTCCTTCACGCGGCGTTGCTGGGTCAGGCTTGCGCCCATTGCCCAATAT
++
+ at CCFFFFFHHGHHIJJJJJJIJJIJJIIJJJJJHIIJJJJIJJJHHHFFCDDEDDDDDDDDDEDDDDDDDDDDDBDDD@DD at CEEDDDDDDDDDDDDDDDDCCDCDDDDDDCDDBDBDDBDDDDDDDDDDDCDDDDDD@DCDCCDDDCCD
+ at HWI-ST1106:815:H154GADXX:1:1101:2116:2218 2:N:0:GAACCT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTCCCCCCATTGTGCAATATCCC
++
+@@<DDFFFHFHHHIJIJJJJJHHIGIJJIJJJJ at FHIJJJGJJJE??EHFFEBBBCDDCDA=A=?B@:<A?59;<BB?(+::(+>C9A5+89BAB?CCA@>4>@C<325090&055505<?@C::>A9??4 at AB@<<CDEC>>>AA:>@C
+ at HWI-ST1106:815:H154GADXX:1:1101:2046:2228 2:N:0:TTAGGC
+TTCAGGTCATAACTTTTGATCTTGCAGGCATCGCCGGAATTTCCCTCCACGGTATAAACACGGCTGCCATCGGTGCCGACAACAATTCCCACATGGTCTGCGGAACCATCCAGATCCCAATCGAAGAAAATGGCATCACCGGGAGCGATG
++
+@@@DADADFHHHHIIIIIIAHHGH at GGCAFIHIIIIIIIIIIHFGGCHIIGIHIHFEEHHFFFDDDBDDDCB@BDDCDDDDDDD?CDDDDDBDDDCCDCCCDB at B9@BC>ACCCCC at CCCDDDBDDB(9<>@ABC>?CAABB>9>@@>?<
+ at HWI-ST1106:815:H154GADXX:1:1101:2092:2229 2:N:0:AGTCAA
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCATCCTGCACGCTACTTGGCTGGTTCAGGCTC
++
+@@@FFDDDHHAHHGIIIII?BGIDHIGGDFHIIIIIIIHCEHEHHHHHFBEFBDCCEECABB at CDCECB?=@BCCCCC@:@CC4 at ACCCCCDC@>BCCC:@>:>A:<9 at CCC@???>9 at BBC:@CACCBBCBB>@@CCC<@+:@C at CCBB
+ at HWI-ST1106:815:H154GADXX:1:1101:2195:2237 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAATCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCTTTACATAACGAATTACTTCTTCACTCACGCGCCGTCGCGGCATCAGAGTTTCTTCCATTTTGCAATATTC
++
+@@@DFFFFHHHHHIJJIHIJJJJJJIJJJJJJJJJJJJJJIJJFHHHHGFEFFFDDDDDDDDDFECDDDDDDD>CCDDCCCDDCDDE###############################################################
+ at HWI-ST1106:815:H154GADXX:1:1101:2147:2238 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTATCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGCTTTCGCCCATTGTGCAATATTCC
++
+@@CFFFFFHHGHHIIJIIJJJJ8BFHIFIJJJJGGIJJDGEHGGGEHHHAEDFFDDEEEE;ACACDDDDDDACDCCDCDDDDDDDEDCD<>>BDDDDDDDDDBDB>CDDDDDBDDDDDDDDDDDDDCACDDD7>BDDDDECCDAC>CD>@
+ at HWI-ST1106:815:H154GADXX:1:1101:2498:2195 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATAATACATACAAAACAGTATACATACTGCACTTTATTCTTATATAAAAGAAGTTTACGACCCATAGAGCCTTCATCCTTCACGCTACTTGGCTGGTTCAGGCTA
++
+@@@D;DDDDDFFFFEIIFE)?FDGD at FFFICFIIIIBEDFIEFFFFFEFEEDD@D>@;A at A??5>>D;AABABDBBBBBBBBBDDDBBBED at AB@B?B:>@@ABB<<BBBBB at B@<ABBBED at BABBBBBBBBBBB<ABB5?@@B>BB?B
+ at HWI-ST1106:815:H154GADXX:1:1101:2263:2198 2:N:0:ACTTGA
+TTCTACAGCGTCTTTCAAGAAACGACCAAGTGTTCGATAATCATGGTGCAAAATTTCACCTACACGGTTACGACTAGCCATTGTTCCGATGTTCACACGTGTGCCGGGGAAACCTTTGATATTGTTGAAAGTCATAGCTGGTCCTTCTTG
++
+1+1ABBD:20<:<E?EEBFCE;+CF??CDD4?:??B8B?DD>B<??CD4BCBDE@@@DA7 at 7)77545;=;;;9??;<=A:>>5:A>29?524>+4>45<2(+4455)0098>8>:>4(4>>:AA><((+:4>A>BAAAA?>A#######
+ at HWI-ST1106:815:H154GADXX:1:1101:2307:2201 2:N:0:TGGATT
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTATCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGCTTTCGCCCATTGTGCAATATTCC
++
+=;?DBDDDHH>DACHGIFHIII?DFEEGFHGIG7 at FEGIIIGGGCHEHCECE>;>BACC;@CD at C?C@?CCCCCCACC:@@ACCA>A999BBBCCCCC:>@8>>?@CBBBB<BBBBBBBBCCC at CC?BCCCB>99<C@@@CCDCCCC at C:
+ at HWI-ST1106:815:H154GADXX:1:1101:2283:2204 2:N:0:CTACGG
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAATGGTATGCATACCAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCCGTCATCCTTCACGCTACTTGGCTGGTTCAGGCTC
++
+===A;2?<00?=AA?ABB*5??AA4=AAAABB<A<AABBBBABB>=AA>;77;))6>@@A>5--(--5;9;?:??59??9:?8=?88383;??:;<;???;88;:==.838:?;79;;;;<????((++8589???88====?#######
+ at HWI-ST1106:815:H154GADXX:1:1101:2453:2206 2:N:0:ATACAC
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAGTCTCACGAGACTAACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTTCCTGCACGCTACTTGGCTGGTTCAGACTC
++
+@=?DDDDDH8DHHGIFGGGGIIGGIIIIIIIIIII<AGI at CHFEHEHFEEEEEDCCACC@B?>CACDC??B@@CCCC33>CC at C@CACC at A:A:>ACCACD at C@C>25??C>@((25)0<0ACCCCCCBBB at B@CCC(:2<9 at CCC@:A:
+ at HWI-ST1106:815:H154GADXX:1:1101:2336:2209 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATTATACATACAAAACAGTATACATACTGCACTTTATTCTAATATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCA
++
+@@@F1BDDFFDHHAGIIIGFGIGFIIHIEHIIIIIIIIIIIHHGFFFFHFFFFFFFEEEDCDCA@>BCD at CDDECDDDDDDDDECACCDEEEECDD?CCDC:CCDCDBDDDDDBCDDCDDECDCCCDDBDDBBCDDDCDDBCCCDDDA?D
+ at HWI-ST1106:815:H154GADXX:1:1101:2378:2210 2:N:0:CTACGG
+GCTTCCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATACATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCTGC
++
+ at CCFFFFDHGFHHGHIJDHIIJ6DDHIG?FFGIIJJJIIHHGHFGFH?CFDFFFECEEDDD>@CEEECDC?CDBDDDDCDDEDD:ACDCDEDD at BC:@CCCCDDDDBDDDCDCBDCDDEACCDCDAABDDDDDCDCCDD?ACC4:9?CB?
+ at HWI-ST1106:815:H154GADXX:1:1101:2470:2220 2:N:0:ATCACG
+AAATTGACGAAATAAACCACCAGCTGACCGAAGATGATGGCAAACTGGTTCCAGCTGACCAACATACCACGGATGTTACTAGGCGCAATCTCACCGATATACATCGGACATACAGCAGATGCCAGACCCACACCGATACCGCCAATCACA
++
+@<@DDADEHHHFHGHJJJJIIJIGGIIIIJJJIIJJJJIIIJJIJJCGHHHGIDCCGIHHEHFDFFFEEEDDDDBCDDDDEDCDDDDDDCCDCDDDBDB>D at ADCDBBDBDDCCDDDDDDDCCCCBBBBABDDDBBDBBCB@BBBCDA at A
+ at HWI-ST1106:815:H154GADXX:1:1101:2434:2220 2:N:0:CGATGT
+TAGGCTGAGTCCATCCTGGATCATTTGTAGTTTCTTCAGAAAGTATATCTTTTCCCTGAGTAGCAATATTAGCATGTTCTCCCTTTTCTATTTTATGCTTGTCAGGAATACCAGTATAAGTTAATGTATGAAGCACTCGAATATATGATT
++
+88+4=22ABDFDFDAFGIFGEFA at FIH?EHEHCEGFIB>CGGIBCFB at FFF?<BFCGEAF?BDFDBFICG=;=FFD at EECC7C>E3=CEDBBDD:@>@ADA6>>@?;?A:>@BB>A:;@A5>;AABEBDB3:@BA?@B<834?ADB at DA:
+ at HWI-ST1106:815:H154GADXX:1:1101:2285:2223 2:N:0:CGAATA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAAGCCACACGTGGCTAACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTCT
++
+@@@FFFFFHHGGHJJJJJJJJJJJJJJJJJIJJJJJJJJJJHHHHHHFFFDEDFEEEDDDDDDDDDDDDDDDDDDDDEDDDDDEDDBBBDEEDDBDDCDEEACDDBDDDCCDDDDDDDDEDDDDDDDDDDDDDCCCDDDD?ACDDDDCDC
+ at HWI-ST1106:815:H154GADXX:1:1101:2390:2234 2:N:0:ATACAC
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTTCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTTGCTGCATCAGGGTTTCCCCCATTGTGCAATATTC
++
+@@@DADFFHHHHHGIIGFGGBHHHGJIGII at GIJJJHHHHFC@DFDFA@@CCE@?B@@DFEDDDD at A>:@CC>@ACDDDCCCCCC at C>?5<9>ACCA@>@CD at ACD?CDBDB9>59 at BDDDD>ACCCBCADD:ACDBCCDDCC at CCACEE
+ at HWI-ST1106:815:H154GADXX:1:1101:2331:2236 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTATTCTACAGGTACTGTCTTGTTTCTTCCCTGTCTAAAGCAGTTTACAATCCGAAAACCTTCTTCCTGCACGCGGCGTCACTGCGTCAGAGTTTCCTCCATTGCGCAATATTC
++
+@@CFDFFDFFFFHIJJJGHIGIIIGGIIIJIGIGB at GGGIJHCE=CECDCDF?AC;C;.65;(;A(=CCDCDDDDD::A53:@:>((+958?>BC?3>(4>A:@C:AC?30<B at BB5<:@AB at BDB@#######################
+ at HWI-ST1106:815:H154GADXX:1:1101:2413:2237 2:N:0:CAGATC
+TACATCTCTTCTCTCCTAATGTTAGTTTTAGAAATAAAGACAGAATCTGCGACCTTCAATCTCACAAATTCGTATGTCCATTTCGTACAATTCGTCCAGTACATCTTTTTTTATCATTTCTTGGGTCGTTCCTTGCGTGAATAACTGCCC
++
+;+1?1<+2<2?,<,2?+2A+<,,?@C?7A7?<=+?@?ABBBBB=7=0?:4?<)7:=7>AB>A4=AB;67===AA>>)>???#####################################################################
+ at HWI-ST1106:815:H154GADXX:1:1101:2368:2242 2:N:0:TCCTCA
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+??BDDDDFHHFGHHJIHHHJGIJIGIJJJJIIJIABHHHIGHJIGIGFHAAABBFDDEEFEEDDDDDCDDDDDDDDDDCDDDDDDCDEEDDDDDDBDDDDDDCCDDDDBDBDDDDDDDDBBDDCDDDDCD3<@@CCC at BDDCACDDDDCC
+ at HWI-ST1106:815:H154GADXX:1:1101:2491:2246 2:N:0:CCTTAA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGAGCTTTCTTGAAAGGTACCGTCAGAACTGTATCATTTCCTATACAGTTTGTTCTTCCCTAACAACAGAAGTTTACAATCCAAAGGACCGTCATCCTTCACGCGGCATTGCTCGTTCA
++
+@@BDDDEFDHGHGIJJJJJIJJHIIIJJJJJJJBHIJJIJJHHEFHHFCBDFCCDB at ACCCCCDEDE@CC;@CCCCCDDBCDC?C:@A@:<CCCBCABAB>AACCDD at C:>C9:ACC98AABDD<A:>CCDCCBB>@D3>CC<@CBBDBC
+ at HWI-ST1106:815:H154GADXX:1:1101:2525:2193 2:N:0:CAGATC
+TTCTGAATAAAGGGAAACTTGTGCACTGACAGTAGAAGCCCCAGAGATATTTTTTTGCTGTTTGATCAATTCTAATGCACTGTTAAAACATGCACTGAAACCAGCTGCAAACAATTGTTCAGGGTTGGTTGCATTTTCGACGCGTTTACC
++
+@??DBDDD?F<ADEDGH;?+<FGFFHIE<FCGFGGGII<GGGHIII at HG?B8BD@;@DAHHA?A=?EC at CCB?DDAC>A at ACAC>C at CABC@A at ACC::@42<?BCC?+::82+4>C>@>@@AB329B2?<@>@>AC39<<>55509<C3
+ at HWI-ST1106:815:H154GADXX:1:1101:2680:2193 2:N:0:GAACCT
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAGTCTCACGAGACTAACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTTCCTGCACGCTACTTGGCTGGTTCAGGCTCT
++
+@@@FFFFFHHGHHJJJJJJJJJJIJJJJGGIIIEHIJJJJHHHHHHHFDDFFFFEEEEEDDDDEDEDDDD at BDCDDDEDDDDEEDDDDDDEEDDDDDDDDEACDDDDDDDDDDDDDDDDBCDCDDCDDDDDDDDDDDDDDACDDCCCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2516:2210 2:N:0:TAGCTT
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAATTCCACACGTGGAAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTCT
++
+<@<B?BA?DDFHFIIIHGGH9 at AFGCD>FGFH<;8DHI at G@EEEHBHF??BECDD66 at CCC:@CCCB?<<<@CCCCCCC at CCA>CCCCCD>@CABBCCCDD@@CA<>BC9>A<CBBCCCEAC at CCCCBBBBBCCCCCCB<?CCCA>@>CC
+ at HWI-ST1106:815:H154GADXX:1:1101:2713:2212 2:N:0:TGACCA
+AGATTGCCACCTCCGTTGATATTATATGTCACTATTCCATTATTGGGACCACTAAACTTTATTAAGGAAGAAGAACCTGAACAAATTGGACTAGCGCCATTAATTGAAATTGTAGCCGTTGGTGTTGAACGAACTGTTACAGCTGCGCTA
++
+?@@D?DFFGGHHGJJHGHGIIJJJJJJJIHIIGIJJIIIIIEHCHGIJJIIJJFHGIIJIJJJIEDEHIGECHHGEHFEBDEFDEEEEEEDDDDCBDDDBCCCADDCACDDCDECCDD at BDD?<<BBAACD<@@DDCACCDDCDCCBBDB
+ at HWI-ST1106:815:H154GADXX:1:1101:2678:2222 2:N:0:CGCTGA
+GCTTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAATCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCATCCTGCACGCTACTTGGCTGGTTCAGGCTCT
++
+@@@FFFFFHHGHHJJJJJJJJJJJIJJIIJJJJJJJJJJJHHHHHHHFFFFFFFEDEEEDDDDDDDDDDDDDCDDDDDDDDDDDDDDDDDDEDDDDDDDDCCCDCBDDDDCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCCDCDADBDC
+ at HWI-ST1106:815:H154GADXX:1:1101:2588:2225 2:N:0:CCTTCT
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATGCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCA
++
+@@@DDFDFHHGGGIJJJJIIJJIIEHFHIJJJJJJJJJJJIHHHHFHBEDDFFFFEEEEEDDD>BDDDEEDCDDDDDDDDDDDEEDDDDDEEDDDDDDACD:ACDDDDDDDDDDDDDDDDEDDDDDCCDDDDDCDDDCDDDCCDDDDDBD
+ at HWI-ST1106:815:H154GADXX:1:1101:2713:2231 2:N:0:TGACCA
+AGATTGCCACCTCCGTTGATATTATATGTCACTATTCCATTATTGGGACCACTAAACTTTATTAAGGAAGAAGAACCTGAACAAATTGGACTAGCGCCATTAATTGAAATTGTAGCCGTTGGTGTTGAACGAACTGTTACAGCTGCGCTA
++
+@@@FFDDFHHHGGJJHIJJGJHJJJJJGHHIJIJJJIJFJJIGHIJJJJIJJJIIIEIIJIJJGHGHCAAGGGIFHHEHCDFEDEEDDEEDDDDC>?DDD at AC@DC>>@CCACDCCCB@<@D88<@B>@CA<BBDCCCDCCD at CDA<>BB
+ at HWI-ST1106:815:H154GADXX:1:1101:2557:2232 2:N:0:CAAGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGATCAGGCTCT
++
+=1?DDBBAD@))@EEDDB;D*?DAADIEDD?AD at ACDEICDDDDCC>=.???D at A;AA63=?3,5(,>(;(55555>8>AAA:::3:>>DD>AA(894:>AAAAA85<>94:><?9?>>A(4:>4>>815<;AA>A>><>(4:2+49<?A
+ at HWI-ST1106:815:H154GADXX:1:1101:2740:2237 2:N:0:AGTTCC
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+@?BDFDFFHHGHGIJIJJJJJJIJJJJJJJIJJJHHIJIJIJJJJJGHHGFHFFFDCEEFEEDDDDDCCCDDCCCCDD:CDDCDDDDEECDDDBDDDDDDDACCBBBDBDDBDDBBDBB at BDBCDCACCD<ABDCDCDDCCC at CDCCACC
+ at HWI-ST1106:815:H154GADXX:1:1101:2527:2244 2:N:0:GTTGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAAAGGCACGCGTGCCTCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTCT
++
+BBBFDFFFHHGHHJJJJJJJJJGGIJIIJJJJJJJJJIJIJHHHHHHFFFDDEEEEDDDDDDDDDDBB>BDBDCDDDCDDDCD at C>?@BDEEDDBDDCDEECCCD?>DDDDCBDDDDDDECDDDDDDDDDBDDDDDDDDDDDDDDDDCDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2603:2248 2:N:0:CAGCAC
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGATGCTTATTCCTTAGCTACCGTCACTGTCTTCGTCACTAAGAAAAGAAGTTTACAATCCGAAAACCGTCATCCTTCACGCGGCGTTGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+B??DDDEDGHGHGIJJJIJJJIGHGGGGHIJJJJJJIJGJJJGIJJJHHHHHFFFCDEC at CDDDBCDDDDDDDCDDDDDDC:@DECDDDDDDDBDBC?@?B at BDDDDDCDDBDDDDDBBBDDDCCDDDCD(2<:4>ABBDDC at CCDD@@A
+ at HWI-ST1106:815:H154GADXX:1:1101:2853:2195 2:N:0:ACTTGA
+AACTATAACTCTTTCCAGGAACTAAATGAAAATCCTATTTTCGCAGATGTTAGCGTATACAATCGTACAGTCATGACACCACAAAGTCTTCCGCATGTAGTAGATGAAGCCATTAAAGCCGCCTATGAGCATAAAGGCGTGGCTATCGTG
++
+=++AB?A::CDADEEIIEEECF9CF at FEEFCEEIIEEEFIDEDIIIIIIIIAE9@ADDDEE at CCCDDDDC=ACDDDAA;=>?;5>>AAAAAA???=?AEED:::>>A>AA?9>>A4>>A<>>;;?AAAAAAAA(+4><;59?>>A>>8<>
+ at HWI-ST1106:815:H154GADXX:1:1101:2884:2198 2:N:0:TGGATT
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTACATGCAAAAAGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTTCCTGCACGCTACTTGGCTGGTTCAGACTC
++
+@@@DADDDDDADHIHBHHGDIIGGIIJIIGDFGGJJJEHHICAAEEHHD at DFDDCAAC>CA?CCEACCDDD@?CDD>ACDDCDDA at CC@CDEDCC8AACCC at ACCCDDDDCCCDCD@BBB?@CAC@?CDDBDBC@@CCDBDCACACACDD
+ at HWI-ST1106:815:H154GADXX:1:1101:2751:2204 2:N:0:AAGCTT
+GCTGCGTTCTTCATCGATGCCGGAACCAAGAGATCCGTTGTTGAAAGTTTTAAATAATTTATATTTTCACTCAGACTTCAATCTTCAGACAGAGTTCGGGGGTGTCTTCGGCGGGCGCGGGCCCGGGGGCGTGAGCCCCCCGGCGGCCAG
++
+ at B@FFFFFHHHHGIJJJJJJJJJJHIIIJJIJJIJJJIHJFHIGIIHHHIJCHIEDHHHHHHGHHFFFFFFFEEEEEEDCACDDDEEDDCDDACCDCBDDD at B@BCDDDDDDDDDDDDBBB<B>5<BDD>>@@BB?ABDBB<BB<B####
+ at HWI-ST1106:815:H154GADXX:1:1101:2785:2207 2:N:0:AAGAAG
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCCTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+?:??DDFDHFAFHCFHIIIIGEDBB0?BFFDFHHHEIFC@)>)=C>CAE?=;@DB?BBDCCD;;CCC>?C>2:>>(,,:ACCCACCCDEC<9<5<<@>CCC>C:A<@B3 at BA9@799<>BBD>C at CDCDD3<@DAAC9<<CCAA>4>@@>
+ at HWI-ST1106:815:H154GADXX:1:1101:2938:2209 2:N:0:CAGATC
+CCAAGAAGGAATCGATTATTTGGCAGGCCTGCCGGATAGCCATCCAAAGGTCTTGATAGTAAAAGAAGGAAGATATGATGAATATATAGAAAGCAGATTATCCAATTTTAAACTTGTGGGAGCAGGAACAGTAGTTATCTCCGGTAATCG
++
+@@@BDDADHD8<FH>FHG<3AFF9EHIGIFEHCFBFGEGAGIIEHIB<FH)@CEGDGHIGHH7=A-?@@;;@@>:>ACDCECDDDDD<A>CCCC??C3>CC>@CCCAAC>C::@@:A4852<>BC at B?18?@(:44:>A3(:5595?C@?
+ at HWI-ST1106:815:H154GADXX:1:1101:2969:2210 2:N:0:CGTCAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATACATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCTG
++
+@@@FFFFAFDFHHGGDEHIIGGIEADGGEGII:;AHIICDE=9?7CEH;?>;>@CCEEAB at B>=CCCDDD at C@@5908C>ACCDDC>>@CDECC at BA:ACDCCDD09?ACCCA<?9C?CDCCACCCDDB>B<@CCCCCBD<AAAACCDD@
+ at HWI-ST1106:815:H154GADXX:1:1101:2909:2214 2:N:0:CCGTCC
+TTATCAAAACTTATCTTATTTTCGAAGTAAAAGTTGAAGCTTTGATGGGGTAAATATAAAAATATATTTCAGATTTTTATTTTTTAAAAACAAATAAAAGTAAAGAATTTCAACTACAAGGTTGTAGTAATGAATAAATTAACAAATAAA
++
+@@@FDDA;?CFDFFHIIBHHFFBE;FHGDHCFH?CFEFFDGGHGAFHGGDFFCGHIHGB at FCFFECGHIGIIGGEGHIGHHCA?BDA>A@@B?BC@>A:A>>@ACCBDDCCDCDDC@@>A?@:?<CCDDEDDCA:C>C:@>>CDCBDDC@
+ at HWI-ST1106:815:H154GADXX:1:1101:2888:2222 2:N:0:GTCGCT
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTTGCTGCATCAGGCTTTCGCCCATTGTGCAATATTCC
++
+<???BB3DDA:8DEEEE<;19 at 0??DDEDCDIIADADDCDDDDDD>AAAAAA?????DAD>AA>><>A>AA:>AAAAAAAAAA>DBA<?>>>?AAAAAA>A>>AA>A?<>>555;>>AAAAAAAAA><<A>>3)59AAA4>AAAAAAEEA
+ at HWI-ST1106:815:H154GADXX:1:1101:2873:2233 2:N:0:ACTTGA
+TCTGCAAGCACTGGTCCTTTGGCTAGTTCTGCTTGTCCCTTTGTTTCTTCATTTAAATGAACCGTTCCAGATACAGGAGCTTTTAGTATTCCTTTTGAAAGTTGATCGTCCAAACTTTTGATAACTGACTGGTTCTTCTCTTGTTTTTCA
++
+:>=2+27AC==<?+2222<33 at 3<3?C at 72?*:?A:1:?BBBA7?A4?A=A<7A=A*?*/99(7-;AA;>77;>>AAAA@@@@@@>>@>>@9=5=?>;;:5;;9=?3559(2(8;=??:38;:????((889?;????=?=??#######
+ at HWI-ST1106:815:H154GADXX:1:1101:2990:2243 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATCC
++
+@@@DDDFFHGFHGHIIJIJJJJIHIIGIIJJJJIJJHHHHFFFFEFFDDCCECDDDDDEFEEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCDCDDDDDDDDDDBDDDBDDDDDDDDDCCCCCDCCDDDDEDDDDECDCDEC
+ at HWI-ST1106:815:H154GADXX:1:1101:2791:2243 2:N:0:CAGATC
+ATTTCTCAATCTTTTCTCTCCGTTGGGATAACAACGATTATGTGGGTATTTGGTGGATTCGGATTGGCCTTTGGACGGGATATCGGCGGTGTTATTTGTAAACCGGCGGGTTTTTTTTTGTTGAGGCATGTTACAAGCTTCCCCAACACG
++
+??=DDBDDHHFHHIIIIEHHIICFEEHGHIIHFHGGFHF=GE0BDG6?DGIH<F at F=CEG=(;EH36??D at BCCCCB@8?BCCCBBB###############################################################
+ at HWI-ST1106:815:H154GADXX:1:1101:3046:2196 2:N:0:AGTTCC
+CCATTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAAATCCACACGTGGATAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTC
++
+@@@DDFFDHGFHHHIJJJJJJIIIIIHHCHHJJJJJJIGGIHHHHHHHFB at DFFFEEEEDBDDDDDCBDBBDDDEDDDEDDDDDDDDDDDECEDDBBD@>C:ACDDBDDDDDCBDDDDDDEDCCCDDDDDDDD at CDCCDDDDDDDCDDC:
+ at HWI-ST1106:815:H154GADXX:1:1101:3147:2203 2:N:0:GGCCTT
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTGTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATTCC
++
+@@@DDDFFGHHFHGHJJIJJJJBDFHIIJIJEIGGGIJJJIJHGHGHGHEFFFDCBBDDDDCDDDDDDDDDDDDDDDDDCDDDDDD at CBB>@DDDDDDCDCCCDDDDDDDDDDDDDDDDDDDCDDCCADDECCCDDDDDDDDECCCDECA
+ at HWI-ST1106:815:H154GADXX:1:1101:3211:2211 2:N:0:AGTGGT
+CCATTACCGCGGCTGCTGGCACGGAATTAGCCGGTCCTTATTCATAAGGTGCATGCAAAAAGTCTCACGAGACTCACTTTATTCCCTTATAAAAGCAGTTTACAACCCATAGGGCCGTCTTCCTGCACGCTACTTGGCTGGTTCAGACTC
++
+@@CDFFFFHHHHHIIIJIJJJJIJJIGIJIHIJGIJJJJJIHHHHGH7??);@CECEEDCBD5 at CCDDBDDDDDDDDDCDDDDEEDDDDDDDEDDDDD@AD:ACCCBDDDDDCDD?BBBABDDDDDDDDDDDDCDDDCDDBCACCCCCCC
+ at HWI-ST1106:815:H154GADXX:1:1101:3127:2215 2:N:0:ATCACG
+GCTTACCGCGGCTGCTGGCACGTATTTAGCCGGAGCTTCTTAGTCAGGTACCGTCACTATCTTCCCTGCTGATAGAGCGTTACATAACGAATTACTTCTTCACTCACGCGGCGTCGCTGCATCAGAGTTTCCTCCATTGTGCAATATTCC
++
++=1AA+A<<)=?7?=<?BA=<:)00=BA?ABAAAAAAB>B>>A>A)=AA>;>',35;=3;;==;?==:;95:9(5::(&0;903:=3;229(8??8=83=:8;=?9(+2)95&00)&&503+(+88:5;?:????73;??:;:??:3;??
+ at HWI-ST1106:815:H154GADXX:1:1101:3233:2216 2:N:0:TTGGTA
+GCTTACCGCGGCTGCTGGCACGTAGTTAGCCGTGGCTTTCTGGTTAGATACCGTCAAGGCGCTAACAGTTACTCTAGCACTTGTTCTTCTCTAACAACAGAGTTTTACGATCCGAAAACCTTCTTCACTCACGCGGCGTTGCTCCGTCAG
++
+@@?DD?DDAAFHDFB?GHHGGG?FFBHH at FHEHGG8@FDGCEHCE>EHH>;C8,9?B>C<?B:8;C3>>@ACCCACCC at CCC@:>>@CCA>CCCC@>18@?9+:@:ACB8++<@7<3>9(9(3::>>:CC39??9<9B at B&&>::><?<>
+ at HWI-ST1106:815:H154GADXX:1:1101:3185:2216 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCACTCACGCGGCGTTGCTGCATCAGGGTTTCCCCCATTGTGCAATATTC
++
+@@@DFDDFHGFHHJJIIJJJJIIDGHIIJJIIJJJJHHHGDFFFFFFEDCCEED at BBDEEDDDDDDDDDDDDDDDDCDCDDCCCDDDDCDBDDDCDDDDDDCDDCCDDDB>@BD@>BBDDCDDDDDDB38<@CDDBDCCDEDCECCCADD
+ at HWI-ST1106:815:H154GADXX:1:1101:3012:2219 2:N:0:GTCGCT
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGGGCTTCTTAGTCAGGTACCGTCATTTTCTTCCCTGCTGATAGAGCTTTACATACCGAGATACTTCTTCACTCACGCGGCGTTGCTGCATCAGGCTTTCGCCCATTGTGCAATATTC
++
+@@@FDFFFFHHHHJJIJIIIJIJIGHJIIJJJJIJJHGHHFFFFFFDCECEECDDBDBEDEDC at CDDCCBDDCDDC@C at ACCCDC>CCDB<BDDDDACC>A at CCDCDCBDBBDB<@@>@CCCCDCCA?<CCDDDDD<?CDDDCDCDDCDB
+ at HWI-ST1106:815:H154GADXX:1:1101:3071:2234 2:N:0:CTACGG
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATACGGTACATACAAAGGAGTATGCATACTCCACTTTATTCCCGTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGACTCT
++
+=>=AA77AA8AC<?A>**1)?AAA:/0?=?AAAAAABBA)=>A>AAA=@=/>>@>>@??===(5;:>??=??55;<??:?;??38)25;;?(8=<988;:;388(859=8:;=9<0838=:??????=<;;;:8=???############
+ at HWI-ST1106:815:H154GADXX:1:1101:3245:2235 2:N:0:CCTTAA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCC
++
+@@BDFDDFHHHGHIJJJJJIIJIDGCHIJJIJJJIJJJJJJJIIHHHHHFCEFFDDCCEDDDDDBBBDCDDDB>@B?ABA?ACCC at CACBBBDDCBCCCCCCCCCCDDD<>@DDDDDBBBBACCDCD<38<>C>?@BCCCDDCD:@ACCC
+ at HWI-ST1106:815:H154GADXX:1:1101:3136:2239 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTACAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCC
++
+@@@BDDDFHHFHHGGIJGIIIIIHHIFHIIIIJJIGIIJJJIIJHHGHGFEFFFDCDEEDEDDDDDDDDDDDDDDDDDB?CCEDDDDDDDDDDDDDDDDACCCDDCDDDDDDDDDDDDDDDDDDDDDD9??CCDDDDCCCDDDECCDDCD
+ at HWI-ST1106:815:H154GADXX:1:1101:3036:2243 2:N:0:CAAGAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATAAAGTACATGCAAACGGGTATCCATACCCGACTTTATTCCTTTATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCTCT
++
+@@CFFFFFHHHHGJJJJJJJJJJGJIJIJJJJIIJJJJJJIHHHHHGGFEFFFFFCCEEDDD;=CCCDDDDDDDDDDDDDDDCCDDDDCEEEDDBBDCDCAACCCDDDDDCDDDDDDDDECDDDDDDBDDBDDCDCDDBBCCDDDCDBDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3201:2246 2:N:0:CTGTCA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATCCTTATTCATATGGTACATACAAAATTCCACACGTGGAAAACTTTATTCCCATATAAAAGAAGTTTACAACCCATAGGGCAGTCATCCTTCACGCTACTTGGCTGGTTCAGGCCTG
++
+BBCFDFFFHHGHHJJJJJIJJJIIIIJJJJJJHBAHIJJJJHHGHHHHFDFC>BDC6;?C@>CDCCBB99?8CCD?::::AD>3:AC94:(:C@??ACDAD::@C2<@?>:@BDBDDC at D@ACCDDDDDDD<>@ACD>?3(4>>@A?2@@
+ at HWI-ST1106:815:H154GADXX:1:1101:3089:2248 2:N:0:ACTTGA
+TCATACGCAAGTTTCAAATGAACTTCCTGAAAGCATTATGGACAGTATACGAGAAGTACGTGATTATTTTGAAGAGTCTACCATTCTTCAGGGAATTGACGTGATTTATGATCGACAGTTTTTGACAGAGCAGCGACGGCTTGCCGATAA
++
+@@@DDFDFH?D:DGGGIEEA<<CHH at EHEEGHIGGGGFGFH>HGGIGGIIIDAHIIEGGH at CEHGIGIIIIFECE??7?DE at C@@;@@A at AC??BBCACC=?<8ACDADCC@:?7<BB>>>A?BBCCC<??:CBB95.55<B@?######
+ at HWI-ST1106:815:H154GADXX:1:1101:3466:2192 2:N:0:CGATGT
+AAAACAAATTCAGTTTCTGAATTGTTATTCAGCGCAGGAAACGAGATGTTTCCGACTAAAATTCCGTTTGCGGTCACAGTAAGTGAGGTAGGTGTAAAAGCTGCTGAGGCGGCTGTCAGCATAATTTTAACGGTTGATGTGGCGTCAAAA
++
+@<@DDDDDFHHDDHGIIIIGIIGHHHHHGIEIFIIIIIDAH>D at FHHGGEHGGII<A at EAAHHHEEFF@AEAB?B?C at C>ACC;>3>A>>C?3:@A at BCCAC:?@CABBCCC<BBACCCCCCCCCBAC:>>?B(8<CACCCCBBBBB9>@
+ at HWI-ST1106:815:H154GADXX:1:1101:3490:2192 2:N:0:TAATCG
+CCATTACCGCGGCTGCTGGCACGTATTTAGCCGGTGCTTCTTAGTCAGGTACCGTCATTTCTTCTTCCCTGCTGATAGAGCTTTACATACCGAAATACTTCTTCGCTCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATAT
++
+@@@DDDDDFHDFDGA at BBD;CDA?DFHEIIDHIEAA at CF@CEGDDDA=C?==?BEACCDDCC at ACCC>CCCBCCCCC>@CCCCCCACEDCC>B5<8 at CC:>@C at B>985 at AB9@@<@BBB@>9ACCCC><3<?C34<9>CAC>CCCCCA@
+ at HWI-ST1106:815:H154GADXX:1:1101:3418:2203 2:N:0:TCACAA
+GCTTACCGCGGCTGCTGGCACGGAGTTAGCCGATGCTTTTTCTTCGGATACTTGCAATACACTACACGTAGCGTACTTTACTCTCCGACAAAAGAGGTTTACAACCCGTAGGGCCGTCTTCCCTCACGCGACTTGGCTGGTTCAGTCTGC
++
+?1 at DDDDDHFAHFIIIGIIGIII<DBGGFIIIGIIIIIIIIIFHH??DECCACACCCCCCCCCCCCCB?CBBBBBBBC@@CCCAC?B>BBB??>BCBCBCCCCCCB@@@5?@@?@BBBB at C@?CCB<?BB@@BBCCCC<>+:@:>>@>>C
+ at HWI-ST1106:815:H154GADXX:1:1101:3308:2210 2:N:0:TTGGTA
+CCATTACCGCGGCTGCTGGCACGTAGTTAGCCGGTGCTTTCTTGTTAGGTACCGTCATTATCGTCCCTAACGACAGGAGTTTGCAATCCGAAAACCTTCTTCCTCCACGCGGCGTCGCTGCATCAGGGTTTCCCCCATTGTGCAATATCC
++
+@@@DDDDFHFFHHGIJJHJIIIGGIIFGIIIEIEHHIIIJJJJJHGGHHE at DFFCACBEEEDDDDDDCDDDDDDDDBDD<?CCCDDDDDDB?BDDDDDDDDCCDDCDDDDDBDDDDDDDDDDDDDDDBA8?ADCCDD?ACEDDDCCCDDD
+ at HWI-ST1106:815:H154GADXX:1:1101:3481:2217 2:N:0:ATCACG
+CGATTCTGCGAGAAACCGATGAGATCGTAGGGGCATGCTGTGAAGTATTGGTTGTGAGCAACAATTCGTTCAAAGAAAGGAGTAAGGTTGTCGTCAGAATAACGGAAGTCGTAAAGTTTATAAACGTGTATTCCATCATAGGCCATATAA
++
+=7=AA,2<AA8A0=@CCA==AB*111:ABAAAAA=BAABAAAABB=ABBAA7=A-;>>AA@>@<>@356;=;;;;=5;?:====9;::39;:;8(9;=??78;<7(80+8989283+88=?;38:;288383:88888???;7:=7:;8?
+ at HWI-ST1106:815:H154GADXX:1:1101:3392:2219 2:N:0:ATCACG
+ATGGGCGGTTACGCAGAATACCGCTTCGGGAGAGCCGGCAATTTCCTCTCCAACTTCTGCTACACGATTTCTCTGATCATCGCCAACGTTGCTATTGCAAGCGGCGTTGTCAGCTACGGTTCTTATGTTTTCGGTTTCAACCTTGATCCG
++
+@@@FDFDFDF?FDHIGGIHIIJBEDHGGEGFBGIGHFF?CBCDDACCCD>CCCCDDDCCCDDDDDDBDDDCEDD>CDCCCCCDB at BD7<ABBCCDDDCDDDBB at BB<>BDDDDDDDCDDCBDDDDCD at D@?@<@8>@AB@><?ACCCAC@
+ at HWI-ST1106:815:H154GADXX:1:1101:3431:2221 2:N:0:TTAGGC
+ATGCTACCTACTCTGAAATTGACGGTACAGCAACAAGCGAAATTGCGACAAGCAGTAATGCATTAATGTTAATCCCTCAGAATGATCTATCGTCAGTCAAGATTACTGTTACTTATTCCACGACTAATGATAATGGCAAAGTATTTGAAG
++
+?==BBDFFGFHHGGIIIIFDCFC at FGHIIIIIIGIIIGHHGIFIIHIIIIIIGIIIGHFHHHGFFFFEEEEEEECECCDDDDDCDDCDCCCB?ABDDDCDDDDACCDA>CCCDDDCEAA at ABBBB<>A>CCDCCDCBC><CAABC@@:@:
diff --git a/t/test2.fastq.gz b/t/test2.fastq.gz
new file mode 100644
index 0000000..c1ac163
Binary files /dev/null and b/t/test2.fastq.gz differ
diff --git a/t/test_interleave.fastq.gz b/t/test_interleave.fastq.gz
new file mode 100644
index 0000000..511b8ac
Binary files /dev/null and b/t/test_interleave.fastq.gz differ
diff --git a/t/test_novlp_1.fastq.gz b/t/test_novlp_1.fastq.gz
new file mode 100644
index 0000000..0be8ceb
Binary files /dev/null and b/t/test_novlp_1.fastq.gz differ
diff --git a/t/test_novlp_2.fastq.gz b/t/test_novlp_2.fastq.gz
new file mode 100644
index 0000000..8696f9d
Binary files /dev/null and b/t/test_novlp_2.fastq.gz differ
diff --git a/t/test_ovlp.fastq.gz b/t/test_ovlp.fastq.gz
new file mode 100644
index 0000000..674c16e
Binary files /dev/null and b/t/test_ovlp.fastq.gz differ
diff --git a/t/trim_1.fastq.gz b/t/trim_1.fastq.gz
new file mode 100644
index 0000000..9b8ca34
Binary files /dev/null and b/t/trim_1.fastq.gz differ
diff --git a/t/trim_2.fastq.gz b/t/trim_2.fastq.gz
new file mode 100644
index 0000000..b676fed
Binary files /dev/null and b/t/trim_2.fastq.gz differ
diff --git a/t/trim_both.fastq.gz b/t/trim_both.fastq.gz
new file mode 100644
index 0000000..9b8ca34
Binary files /dev/null and b/t/trim_both.fastq.gz differ
diff --git a/t/trim_head.fastq.gz b/t/trim_head.fastq.gz
new file mode 100644
index 0000000..e275025
Binary files /dev/null and b/t/trim_head.fastq.gz differ
diff --git a/t/trim_tail.fastq.gz b/t/trim_tail.fastq.gz
new file mode 100644
index 0000000..2eb1cf1
Binary files /dev/null and b/t/trim_tail.fastq.gz differ
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/htqc.git
More information about the debian-med-commit
mailing list