1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 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 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * This interface allows users to define their own file input sources from which 30 * DSFML can load resources. 31 * 32 * DSFML resource classes like $(TEXTURE_LINK) and $(SOUNDBUFFER_LINK) provide 33 * `loadFromFile` and `loadFromMemory` functions, which read data from 34 * conventional sources. However, if you have data coming from a different source 35 * (over a network, embedded, encrypted, compressed, etc) you can derive your own 36 * class from $(U InputStream) and load DSFML resources with their 37 * `loadFromStream` function. 38 * 39 * Usage example: 40 * --- 41 * // custom stream class that reads from inside a zip file 42 * class ZipStream : InputStream 43 * { 44 * public: 45 * 46 * ZipStream(string archive); 47 * 48 * bool open(string filename); 49 * 50 * long read(void[] data); 51 * 52 * long seek(long position); 53 * 54 * long tell(); 55 * 56 * long getSize(); 57 * 58 * private: 59 * 60 * ... 61 * }; 62 * 63 * // now you can load textures... 64 * auto texture = new Texture(); 65 * auto stream = new ZipStream("resources.zip"); 66 * stream.open("images/img.png"); 67 * texture.loadFromStream(stream); 68 * 69 * // musics... 70 * auto music = new Music(); 71 * auto stream = new ZipStream("resources.zip"); 72 * stream.open("musics/msc.ogg"); 73 * music.openFromStream(stream); 74 * 75 * // etc. 76 * --- 77 */ 78 module dsfml.system.inputstream; 79 80 /** 81 * Interface for custom file input streams. 82 */ 83 interface InputStream 84 { 85 /** 86 * Read data from the stream. 87 * 88 * Params: 89 * data = Buffer where to copy the read data 90 * and sized to the amount of bytes to be read 91 * 92 * Returns: The number of bytes actually read, or -1 on error. 93 */ 94 long read(void[] data); 95 96 /** 97 * Change the current reading position. 98 * Params: 99 * position = The position to seek to, from the beginning 100 * 101 * Returns: The position actually sought to, or -1 on error. 102 */ 103 long seek(long position); 104 105 /** 106 * Get the current reading position in the stream. 107 * 108 * Returns: The current position, or -1 on error. 109 */ 110 long tell(); 111 112 /** 113 * Return the size of the stream. 114 * 115 * Returns: Total number of bytes available in the stream, or -1 on error. 116 */ 117 long getSize(); 118 } 119 120 unittest 121 { 122 //version(DSFML_Unittest_System) 123 version(none) //temporarily not doing this test 124 { 125 import dsfml.graphics.texture; 126 import std.stdio; 127 128 //File Stream ported from Laurent's example here: 129 //http://www.sfml-dev.org/tutorials/2.0/system-stream.php 130 131 class FileStream:InputStream 132 { 133 File m_file; 134 135 this() 136 { 137 // Constructor code 138 } 139 bool open(string fileName) 140 { 141 try 142 { 143 m_file.open(fileName); 144 } 145 catch(Exception e) 146 { 147 writeln(e.msg); 148 } 149 150 return m_file.isOpen; 151 } 152 153 long read(void[] data) 154 { 155 156 if(m_file.isOpen) 157 { 158 return m_file.rawRead(data).length; 159 } 160 else 161 { 162 return -1; 163 } 164 } 165 166 long seek(long position) 167 { 168 if(m_file.isOpen) 169 { 170 m_file.seek(position); 171 return tell(); 172 } 173 else 174 { 175 return -1; 176 } 177 } 178 179 long tell() 180 { 181 182 if(m_file.isOpen) 183 { 184 return m_file.tell; 185 } 186 else 187 { 188 return -1; 189 } 190 } 191 192 long getSize() 193 { 194 if(m_file.isOpen) 195 { 196 long position = m_file.tell; 197 198 m_file.seek(0,SEEK_END); 199 200 long size = tell(); 201 202 seek(position); 203 204 return size; 205 } 206 else 207 { 208 return -1; 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 auto failStream = new FileStream(); 221 failStream.open("nonexistantTexture.png");//doesn't open the stream, but you should be checking if open returns true 222 streamTexture.loadFromStream(failStream);//prints errors to err 223 224 writeln(); 225 writeln("Using a basic file stream to load a texture that exists."); 226 auto successStream = new FileStream(); 227 successStream.open("res/TestImage.png");//using a png of Crono for now. Will replace with something that won't get me in trouble 228 assert(streamTexture.loadFromStream(successStream)); 229 230 writeln("Texture loaded!"); 231 232 writeln(); 233 } 234 }