1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2017 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 */ 24 25 /** 26 * This class allows users to define their own file input sources from which 27 * DSFML can load resources. 28 * 29 * DSFML resource classes like $(TEXTURE_LINK) and $(SOUNDBUFFER_LINK) provide 30 * `loadFromFile` and `loadFromMemory` functions, which read data from 31 * conventional sources. However, if you have data coming from a different source 32 * (over a network, embedded, encrypted, compressed, etc) you can derive your own 33 * class from $(U InputStream) and load DSFML resources with their 34 * `loadFromStream` function. 35 * 36 * Usage example: 37 * --- 38 * // custom stream class that reads from inside a zip file 39 * class ZipStream : InputStream 40 * { 41 * public: 42 * 43 * ZipStream(string archive); 44 * 45 * bool open(string filename); 46 * 47 * long read(void[] data); 48 * 49 * long seek(long position); 50 * 51 * long tell(); 52 * 53 * long getSize(); 54 * 55 * private: 56 * 57 * ... 58 * }; 59 * 60 * // now you can load textures... 61 * auto texture = new Texture(); 62 * auto stream = new ZipStream("resources.zip"); 63 * stream.open("images/img.png"); 64 * texture.loadFromStream(stream); 65 * 66 * // musics... 67 * auto music = new Music(); 68 * auto stream = new ZipStream("resources.zip"); 69 * stream.open("musics/msc.ogg"); 70 * music.openFromStream(stream); 71 * 72 * // etc. 73 * --- 74 */ 75 module dsfml.system.inputstream; 76 77 /** 78 * Interface for custom file input streams. 79 */ 80 interface InputStream 81 { 82 /** 83 * Read data from the stream. 84 * 85 * Params: 86 * data = Buffer where to copy the read data 87 * and sized to the amount of bytes to be read 88 * 89 * Returns: The number of bytes actually read, or -1 on error. 90 */ 91 long read(void[] data); 92 93 /** 94 * Change the current reading position. 95 * Params: 96 * position = The position to seek to, from the beginning 97 * 98 * Returns: The position actually sought to, or -1 on error. 99 */ 100 long seek(long position); 101 102 /** 103 * Get the current reading position in the stream. 104 * 105 * Returns: The current position, or -1 on error. 106 */ 107 long tell(); 108 109 /** 110 * Return the size of the stream. 111 * 112 * Returns: Total number of bytes available in the stream, or -1 on error. 113 */ 114 long getSize(); 115 } 116 117 unittest 118 { 119 //version(DSFML_Unittest_System) 120 version(none) //temporarily not doing this test 121 { 122 import dsfml.graphics.texture; 123 import std.stdio; 124 125 //File Stream ported from Laurent's example here: 126 //http://www.sfml-dev.org/tutorials/2.0/system-stream.php 127 128 class FileStream:InputStream 129 { 130 File m_file; 131 132 this() 133 { 134 // Constructor code 135 } 136 bool open(string fileName) 137 { 138 try 139 { 140 m_file.open(fileName); 141 } 142 catch(Exception e) 143 { 144 writeln(e.msg); 145 } 146 147 return m_file.isOpen; 148 } 149 150 long read(void[] data) 151 { 152 153 if(m_file.isOpen) 154 { 155 return m_file.rawRead(data).length; 156 } 157 else 158 { 159 return -1; 160 } 161 } 162 163 long seek(long position) 164 { 165 if(m_file.isOpen) 166 { 167 m_file.seek(position); 168 return tell(); 169 } 170 else 171 { 172 return -1; 173 } 174 } 175 176 long tell() 177 { 178 179 if(m_file.isOpen) 180 { 181 return m_file.tell; 182 } 183 else 184 { 185 return -1; 186 } 187 } 188 189 long getSize() 190 { 191 if(m_file.isOpen) 192 { 193 long position = m_file.tell; 194 195 m_file.seek(0,SEEK_END); 196 197 long size = tell(); 198 199 seek(position); 200 201 return size; 202 } 203 else 204 { 205 return -1; 206 } 207 } 208 } 209 210 211 212 213 writeln("Unit test for InputStream"); 214 215 auto streamTexture = new Texture(); 216 217 writeln(); 218 writeln("Using a basic file stream to load a non existant texture to confirm correct errors are found."); 219 220 221 auto failStream = new FileStream(); 222 failStream.open("nonexistantTexture.png");//doesn't open the stream, but you should be checking if open returns true 223 streamTexture.loadFromStream(failStream);//prints errors to err 224 225 writeln(); 226 writeln("Using a basic file stream to load a texture that exists."); 227 auto successStream = new FileStream(); 228 successStream.open("res/TestImage.png");//using a png of Crono for now. Will replace with something that won't get me in trouble 229 assert(streamTexture.loadFromStream(successStream)); 230 231 writeln("Texture loaded!"); 232 233 writeln(); 234 } 235 }