Changeset 11:b940f267419e
- Timestamp:
- 02/21/08 04:05:33
(11 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- branch:
- default
- convert_revision:
- af0969213fc9be30ef4b4d65563d1da8d8290742
- Message:
Options class created & changes to mergetag exception messages.
Options class created (barebones). Loading/saving from Init.
Init no longer runs cleanup functions after initialisation failure.
Improved mergetag exception messages & error reporting.
committer: Diggory Hardy <diggory.hardy@gmail.com>
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r10 |
r11 |
|
| 2 | 2 | |
|---|
| 3 | 3 | To do: |
|---|
| 4 | | * Write Input unittests; remove untested notes |
|---|
| 5 | 4 | * Why doesn't input.config filtering via headers "Configs" work? |
|---|
| 6 | 5 | * add options support; in particular for whether or not to use threads (and adjust Init to use this). |
|---|
| … | … | |
| 35 | 34 | |
|---|
| 36 | 35 | Done (for git log message): |
|---|
| 37 | | * Init threads now catch own exceptions. |
|---|
| 38 | | * Assigned some inputID devisions. |
|---|
| 39 | | * add remaining SDL event support |
|---|
| 40 | | * Rewrote most of mde.mergetag.defaultdata using generic programming to generate read & write rules for all types. As a result, defaultdata can now write properly. |
|---|
| 41 | | * Axis output now stored with short instead of real. |
|---|
| 42 | | * Input unittest |
|---|
| 43 | | * Moved mde/text to scrapple |
|---|
| 44 | | * DefaultData unittest. Then commit. |
|---|
| | 36 | * Options class created (barebones). Loading/saving from Init. |
|---|
| | 37 | * Init no longer runs cleanup functions after initialisation failure. |
|---|
| | 38 | * Improved mergetag exception messages & error reporting. |
|---|
| r10 |
r11 |
|
| 9 | 9 | |
|---|
| 10 | 10 | [mde/mde.d] |
|---|
| 11 | | version (Posix) { |
|---|
| 12 | | target=bin/mde |
|---|
| 13 | | } else version (Windows) { |
|---|
| 14 | | target=bin/mde.exe |
|---|
| 15 | | } |
|---|
| | 11 | target=bin/mde |
|---|
| 16 | 12 | |
|---|
| 17 | 13 | [test/mdeTest.d] |
|---|
| | 14 | buildflags=-debug -debug=mdeUnitTest -unittest |
|---|
| | 15 | target=bin/mdeTest |
|---|
| | 16 | noinstall |
|---|
| 18 | 17 | version (Posix) { |
|---|
| 19 | | buildflags=-L-ldl -debug=mdeUnitTest -unittest |
|---|
| 20 | | target=bin/mdeTest |
|---|
| 21 | | } else version (Windows) { |
|---|
| 22 | | warn Extra linking probably needed! |
|---|
| 23 | | buildflags=-debug=mdeUnitTest -unittest |
|---|
| 24 | | target=bin/mdeTest.exe |
|---|
| | 18 | buildflags+=-L-ldl |
|---|
| | 19 | } else { |
|---|
| | 20 | warn Only posix builds have been tested; elsewhere other libraries will probably need to be linked. |
|---|
| 25 | 21 | } |
|---|
| 26 | | noinstall |
|---|
| r10 |
r11 |
|
| 39 | 39 | } |
|---|
| 40 | 40 | |
|---|
| | 41 | class optionsLoadException : mdeException { |
|---|
| | 42 | // NOTE: if symbol is final, it can't be modified in the static this(), but as const it can |
|---|
| | 43 | static const char[] symbol; |
|---|
| | 44 | static this () { symbol = super.symbol ~ ".options"; } |
|---|
| | 45 | char[] getSymbol () { |
|---|
| | 46 | return symbol; |
|---|
| | 47 | } |
|---|
| | 48 | |
|---|
| | 49 | this (char[] msg) { |
|---|
| | 50 | super(msg); |
|---|
| | 51 | } |
|---|
| | 52 | } |
|---|
| | 53 | |
|---|
| 41 | 54 | debug (mdeUnitTest) { |
|---|
| 42 | 55 | import tango.util.log.Log : Log, Logger; |
|---|
| … | … | |
| 45 | 58 | static this() { |
|---|
| 46 | 59 | logger = Log.getLogger ("mde.events"); |
|---|
| | 60 | logger.info ("Got logger!"); |
|---|
| 47 | 61 | } |
|---|
| 48 | 62 | |
|---|
| r10 |
r11 |
|
| 8 | 8 | import mde.exception; |
|---|
| 9 | 9 | |
|---|
| | 10 | import mde.options; |
|---|
| 10 | 11 | import mde.events; |
|---|
| 11 | 12 | import global = mde.global; |
|---|
| … | … | |
| 22 | 23 | import derelict.sdl.sdl; |
|---|
| 23 | 24 | import derelict.util.exception; |
|---|
| 24 | | |
|---|
| 25 | | private Logger logger; |
|---|
| 26 | 25 | |
|---|
| 27 | 26 | /** |
|---|
| … | … | |
| 40 | 39 | root.addAppender(new ConsoleAppender); |
|---|
| 41 | 40 | } |
|---|
| 42 | | |
|---|
| 43 | | logger = Log.getLogger ("mde.init"); |
|---|
| 44 | 41 | } |
|---|
| 45 | 42 | static ~this() |
|---|
| … | … | |
| 79 | 76 | * be run simultaneously in separate threads. */ |
|---|
| 80 | 77 | |
|---|
| 81 | | bool initFailure = false; // Set true if something goes wrong and we need to abort. |
|---|
| 82 | 78 | void setFailure () { // For synchronization, although shouldn't be necessary |
|---|
| 83 | 79 | synchronized initFailure = true; |
|---|
| … | … | |
| 85 | 81 | void delegate() [] initFuncs = [ |
|---|
| 86 | 82 | delegate void() { |
|---|
| 87 | | logger = Log.getLogger ("mde.init.Init.SDL"); |
|---|
| | 83 | Logger logger = Log.getLogger ("mde.init.Init.SDL"); |
|---|
| | 84 | |
|---|
| 88 | 85 | // Inits SDL and related stuff (joystick). |
|---|
| 89 | 86 | try { |
|---|
| … | … | |
| 114 | 111 | openJoysticks (); // after SDL init |
|---|
| 115 | 112 | addCleanupFct (&closeJoysticks); |
|---|
| | 113 | }, |
|---|
| | 114 | delegate void() { |
|---|
| | 115 | Logger logger = Log.getLogger ("mde.init.Init.Options"); |
|---|
| | 116 | |
|---|
| | 117 | try { |
|---|
| | 118 | Options.load(); |
|---|
| | 119 | } catch (optionsLoadException e) { |
|---|
| | 120 | logger.fatal ("Loading options failed; message:"); |
|---|
| | 121 | logger.fatal (e.msg); |
|---|
| | 122 | setFailure(); |
|---|
| | 123 | return; |
|---|
| | 124 | } |
|---|
| | 125 | addCleanupFct (&Options.save); // not strictly cleanup, but needs to be called somewhere |
|---|
| 116 | 126 | } |
|---|
| 117 | 127 | ]; |
|---|
| … | … | |
| 158 | 168 | runCleanupFcts(); |
|---|
| 159 | 169 | |
|---|
| | 170 | logger.fatal ("Init failed"); |
|---|
| 160 | 171 | // Throw an exception to signal failure and prevent DTOR from also running. |
|---|
| 161 | 172 | throw new initException ("Initialisation failed due to above exceptions."); |
|---|
| … | … | |
| 168 | 179 | ~this() |
|---|
| 169 | 180 | { |
|---|
| 170 | | runCleanupFcts(); // if threading, note not all functions can be called simultaeneously |
|---|
| | 181 | if (!initFailure) { |
|---|
| | 182 | logger.info ("Cleaning up..."); |
|---|
| | 183 | runCleanupFcts(); // if threading, note not all functions can be called simultaeneously |
|---|
| | 184 | logger.info ("Done!"); |
|---|
| | 185 | } |
|---|
| 171 | 186 | } |
|---|
| 172 | 187 | |
|---|
| … | … | |
| 189 | 204 | } |
|---|
| 190 | 205 | } |
|---|
| | 206 | |
|---|
| | 207 | /* This is set true by this() if something goes wrong and we need to abort. |
|---|
| | 208 | * If it's true, no cleanup should be done by the DTOR (since the DTOR still runs after an |
|---|
| | 209 | * exception has been thrown). */ |
|---|
| | 210 | private bool initFailure = false; |
|---|
| | 211 | |
|---|
| | 212 | debug (mdeUnitTest) unittest { |
|---|
| | 213 | /* Fake init and cleanup. This happens before the CTOR runs so the extra Init.runCleanupFcts() |
|---|
| | 214 | * call isn't going to mess things up. The extra function called by runCleanupFcts won't cause |
|---|
| | 215 | * any harm either. */ |
|---|
| | 216 | static bool initialised = false; |
|---|
| | 217 | static void cleanup () { initialised = false; } |
|---|
| | 218 | |
|---|
| | 219 | static void init () { |
|---|
| | 220 | initialised = true; |
|---|
| | 221 | Init.addCleanupFct (&cleanup); |
|---|
| | 222 | } |
|---|
| | 223 | |
|---|
| | 224 | init(); |
|---|
| | 225 | assert (initialised); |
|---|
| | 226 | Init.runCleanupFcts(); |
|---|
| | 227 | assert (!initialised); |
|---|
| | 228 | |
|---|
| | 229 | logger.info ("Unittest complete."); |
|---|
| | 230 | } |
|---|
| 191 | 231 | } |
|---|
| 192 | | |
|---|
| 193 | | debug (mdeUnitTest) unittest { |
|---|
| 194 | | /* Fake init and cleanup. This happens before the CTOR runs so the extra Init.runCleanupFcts() |
|---|
| 195 | | * call isn't going to mess things up. The extra function called by runCleanupFcts won't cause |
|---|
| 196 | | * any harm either. */ |
|---|
| 197 | | static bool initialised = false; |
|---|
| 198 | | static void cleanup () { initialised = false; } |
|---|
| 199 | | |
|---|
| 200 | | static void init () { |
|---|
| 201 | | initialised = true; |
|---|
| 202 | | Init.addCleanupFct (&cleanup); |
|---|
| 203 | | } |
|---|
| 204 | | |
|---|
| 205 | | init(); |
|---|
| 206 | | assert (initialised); |
|---|
| 207 | | Init.runCleanupFcts(); |
|---|
| 208 | | assert (!initialised); |
|---|
| 209 | | |
|---|
| 210 | | logger.info ("Unittest complete."); |
|---|
| 211 | | } |
|---|
| r10 |
r11 |
|
| 181 | 181 | break; |
|---|
| 182 | 182 | |
|---|
| 183 | | case SDL_JOYBALLMOTION: // NOTE: untested |
|---|
| | 183 | case SDL_JOYBALLMOTION: |
|---|
| 184 | 184 | outQueue[]* p = (Config.M.JOYBALL | (event.jball.which << 12) | event.jball.ball) in config.relMotion; |
|---|
| 185 | 185 | if (p) foreach (outQueue q; *p) { |
|---|
| … | … | |
| 188 | 188 | break; |
|---|
| 189 | 189 | |
|---|
| 190 | | case SDL_JOYHATMOTION: // NOTE: untested |
|---|
| | 190 | case SDL_JOYHATMOTION: |
|---|
| 191 | 191 | static ubyte[uint] oldJHatVals; // necessary to store this to know which "axis" changed |
|---|
| 192 | 192 | |
|---|
| … | … | |
| 298 | 298 | short[inputID] axis; // Table of axes states |
|---|
| 299 | 299 | ushort mouse_x, mouse_y; // Current screen coords of the window manager mouse |
|---|
| 300 | | // FIXME: might need a bit of work... at any rate defining a default ID. |
|---|
| 301 | 300 | RelPair[inputID] relMotion; // Table of relative mouse / joystick ball motions |
|---|
| 302 | 301 | |
|---|
| 303 | | // FIXME: these need to be more like multimaps, supporting multiple dgs (also some means of removal?) |
|---|
| | 302 | // FIXME: currently no means of removal |
|---|
| 304 | 303 | ButtonCallback[][inputID] buttonCallbacks; |
|---|
| 305 | 304 | AxisCallback[][inputID] axisCallbacks; |
|---|
| r10 |
r11 |
|
| 10 | 10 | import mde.events; |
|---|
| 11 | 11 | import mde.scheduler; |
|---|
| | 12 | import mde.options; // greeting message |
|---|
| 12 | 13 | import mde.exception; |
|---|
| 13 | 14 | |
|---|
| … | … | |
| 24 | 25 | int main() |
|---|
| 25 | 26 | { |
|---|
| | 27 | //BEGIN Initialisation |
|---|
| 26 | 28 | Logger logger = Log.getLogger ("mde.mde"); |
|---|
| 27 | 29 | |
|---|
| … | … | |
| 41 | 43 | } |
|---|
| 42 | 44 | } ); |
|---|
| | 45 | //END Initialisation |
|---|
| | 46 | |
|---|
| | 47 | logger.info (options.greeting); |
|---|
| 43 | 48 | |
|---|
| 44 | 49 | while (global.run) { |
|---|
| r10 |
r11 |
|
| 19 | 19 | super(msg); |
|---|
| 20 | 20 | } |
|---|
| 21 | | this () {} |
|---|
| | 21 | this () { // Only called when an unexpected exception/error occurs |
|---|
| | 22 | super ("Unknown exception"); |
|---|
| | 23 | } |
|---|
| 22 | 24 | } |
|---|
| 23 | 25 | |
|---|
| 24 | 26 | /** Thrown on file IO errors. */ |
|---|
| 25 | 27 | class MTFileIOException : MTException { |
|---|
| 26 | | this () {} |
|---|
| | 28 | this () { |
|---|
| | 29 | super ("File IO exception"); |
|---|
| | 30 | } |
|---|
| 27 | 31 | } |
|---|
| 28 | 32 | |
|---|
| 29 | 33 | /** Thrown on unknown format errors; when reading or writing and the filetype cannot be guessed. */ |
|---|
| 30 | 34 | class MTFileFormatException : MTException { |
|---|
| 31 | | this () {} |
|---|
| | 35 | this () { |
|---|
| | 36 | super ("File format exception"); |
|---|
| | 37 | } |
|---|
| | 38 | } |
|---|
| | 39 | |
|---|
| | 40 | /** Thrown on syntax errors when reading; bad tags or unexpected EOF. */ |
|---|
| | 41 | class MTSyntaxException : MTException { |
|---|
| | 42 | this () { |
|---|
| | 43 | super ("Syntax exception"); |
|---|
| | 44 | } |
|---|
| 32 | 45 | } |
|---|
| 33 | 46 | |
|---|
| … | … | |
| 35 | 48 | * unrecognised type field. */ |
|---|
| 36 | 49 | class MTUnknownTypeException : MTException { |
|---|
| 37 | | this () {} |
|---|
| | 50 | this () { |
|---|
| | 51 | super ("Unknown type"); |
|---|
| | 52 | } |
|---|
| 38 | 53 | this (char[] msg) { |
|---|
| 39 | 54 | super (msg); |
|---|
| … | … | |
| 44 | 59 | * (really just to make whoever called addTag to log a warning saying where the error occured). */ |
|---|
| 45 | 60 | class MTaddTagParseException : MTException { |
|---|
| 46 | | this () {} |
|---|
| | 61 | this () { |
|---|
| | 62 | super ("Parse exception within addTag"); |
|---|
| | 63 | } |
|---|
| 47 | 64 | } |
|---|
| 48 | 65 | |
|---|
| | 66 | /+ |
|---|
| 49 | 67 | /// Thrown by TypeView.parse on errors. |
|---|
| 50 | 68 | class MTBadTypeStringException : MTException { |
|---|
| 51 | 69 | this () {} |
|---|
| 52 | 70 | } |
|---|
| | 71 | +/ |
|---|
| 53 | 72 | |
|---|
| 54 | 73 | /// Thrown by *Writer.write. |
|---|
| 55 | 74 | class MTNoDataSetException : MTException { |
|---|
| 56 | | this (char[] msg) { |
|---|
| 57 | | super(msg); |
|---|
| | 75 | this () { |
|---|
| | 76 | super ("No dataset"); |
|---|
| 58 | 77 | } |
|---|
| 59 | 78 | } |
|---|
| r10 |
r11 |
|
| 39 | 39 | * ----------------------- |
|---|
| 40 | 40 | * |
|---|
| 41 | | * Only a child-class of MTException will ever be thrown, currently MTFileIOException if the file |
|---|
| 42 | | * could not be read or MTFileFormatException on any error when parsing the file. |
|---|
| | 41 | * Throws: |
|---|
| | 42 | * $(TABLE |
|---|
| | 43 | * $(TR $(TH Exception) $(TH Thrown when)) |
|---|
| | 44 | * $(TR $(TD MTFileIOException) $(TD An error occurs while opening the file)) |
|---|
| | 45 | * $(TR $(TD MTFileFormatException) $(TD The file doesn't start with a recognised header/version)) |
|---|
| | 46 | * $(TR $(TD MTSyntaxException) $(TD A file syntax error occurs)) |
|---|
| | 47 | * $(TR $(TD MTException) $(TD An unexpected error occurs)) |
|---|
| | 48 | * ) |
|---|
| | 49 | * Note that all exceptions extend MTException and when any exception is thrown the class is |
|---|
| | 50 | * rendered unusable: any subsequent calls to read will be ignored. |
|---|
| 43 | 51 | * |
|---|
| 44 | 52 | * Threading: Separate instances of Reader should be thread-safe provided access to the same |
|---|
| … | … | |
| 162 | 170 | else endOfHeader = parseSection (6,null); |
|---|
| 163 | 171 | } |
|---|
| 164 | | // Was intended to close file, but file is closed within CTOR anyway. |
|---|
| 165 | | public ~this () { |
|---|
| 166 | | } |
|---|
| 167 | 172 | //END METHODS: CTOR / DTOR |
|---|
| 168 | 173 | |
|---|
| … | … | |
| 307 | 312 | uint pos_s = pos; |
|---|
| 308 | 313 | fbufLocateDataTagChar (pos, false); // find end of type section |
|---|
| 309 | | if (fbuf[pos] != '|') throwMTErr (ErrDTAG); |
|---|
| | 314 | if (fbuf[pos] != '|') throwMTErr (ErrDTAG, new MTSyntaxException); |
|---|
| 310 | 315 | char[] type = fbuf[pos_s..pos]; |
|---|
| 311 | 316 | |
|---|
| … | … | |
| 315 | 320 | pos_s = pos; |
|---|
| 316 | 321 | fbufLocateDataTagChar (pos, false); // find end of type section |
|---|
| 317 | | if (fbuf[pos] != '=') throwMTErr (ErrDTAG); |
|---|
| | 322 | if (fbuf[pos] != '=') throwMTErr (ErrDTAG, new MTSyntaxException); |
|---|
| 318 | 323 | ID tagID = cast(ID) fbuf[pos_s..pos]; |
|---|
| 319 | 324 | |
|---|
| … | … | |
| 322 | 327 | // Data section of tag: |
|---|
| 323 | 328 | pos_s = pos; |
|---|
| 324 | | fbufLocateDataTagChar (pos, true); // find end of data section |
|---|
| 325 | | if (fbuf[pos] != '>') throwMTErr (ErrDTAG); |
|---|
| | 329 | fbufLocateDataTagChar (pos, true); // find end of data section |
|---|
| | 330 | if (fbuf[pos] != '>') throwMTErr (ErrDTAG, new MTSyntaxException); |
|---|
| 326 | 331 | char[] data = fbuf[pos_s..pos]; |
|---|
| 327 | 332 | |
|---|
| … | … | |
| 342 | 347 | logger.error ("Unknown error occured" ~ ErrInFile ~ ':'); |
|---|
| 343 | 348 | logger.error (e.msg); |
|---|
| 344 | | throw e; // Fatal to Reader |
|---|
| | 349 | throwMTErr (e.msg); // Fatal to Reader |
|---|
| 345 | 350 | } |
|---|
| 346 | 351 | } else comment = false; // cancel comment status now |
|---|
| … | … | |
| 366 | 371 | // variable is reset at end of comment |
|---|
| 367 | 372 | } else // must be an error |
|---|
| 368 | | throwMTErr ("Invalid character (or sequence starting \"!\") outside of tag" ~ ErrInFile); |
|---|
| | 373 | throwMTErr ("Invalid character (or sequence starting \"!\") outside of tag" ~ ErrInFile, new MTSyntaxException); |
|---|
| 369 | 374 | } |
|---|
| 370 | 375 | // if code execution reaches here, we're at EOF |
|---|
| … | … | |
| 384 | 389 | if (fbuf[pos] == '}' || fbuf[pos] == '{') break; |
|---|
| 385 | 390 | |
|---|
| 386 | | if (fbuf[pos] != '}') throwMTErr ("Bad section tag format: not {id}" ~ ErrInFile); |
|---|
| | 391 | if (fbuf[pos] != '}') throwMTErr ("Bad section tag format: not {id}" ~ ErrInFile, new MTSyntaxException); |
|---|
| 387 | 392 | ID id = cast(ID) fbuf[start..pos]; |
|---|
| 388 | 393 | fbufIncrement(pos); |
|---|
| … | … | |
| 393 | 398 | private void fbufIncrement(inout uint pos) { |
|---|
| 394 | 399 | ++pos; |
|---|
| 395 | | if (pos >= fbuf.length) throwMTErr("Unexpected EOF" ~ ErrInFile); |
|---|
| 396 | | } |
|---|
| 397 | | |
|---|
| 398 | | private void throwMTErr (char[] msg, MTException exc = new MTFileFormatException) { |
|---|
| | 400 | if (pos >= fbuf.length) throwMTErr("Unexpected EOF" ~ ErrInFile, new MTSyntaxException); |
|---|
| | 401 | } |
|---|
| | 402 | |
|---|
| | 403 | private void throwMTErr (char[] msg, MTException exc = new MTException) { |
|---|
| 399 | 404 | fatal = true; // if anyone catches the error and tries to do anything --- we're dead now |
|---|
| 400 | 405 | logger.error (msg); // report the error |
|---|
| r10 |
r11 |
|
| 52 | 52 | * |
|---|
| 53 | 53 | * An exception is thrown if neither test can deduce the writing method. |
|---|
| | 54 | * |
|---|
| | 55 | * Use as: |
|---|
| | 56 | * ----------------------- |
|---|
| | 57 | * DataSet dataset; // contains data to write |
|---|
| | 58 | * IWriter foo; |
|---|
| | 59 | * try { |
|---|
| | 60 | * foo = makeWriter("foo.mtt", dataset); |
|---|
| | 61 | * foo.write(); |
|---|
| | 62 | * } |
|---|
| | 63 | * catch (MTException) {} |
|---|
| | 64 | * ----------------------- |
|---|
| | 65 | * |
|---|
| | 66 | * Throws: |
|---|
| | 67 | * MTFileFormatException if unable to determine writing format or use requested format. |
|---|
| 54 | 68 | */ |
|---|
| 55 | 69 | IWriter makeWriter (char[] path, DataSet dataset = null, WriterMethod method = WriterMethod.Unspecified) { |
|---|
| … | … | |
| 57 | 71 | } |
|---|
| 58 | 72 | /** ditto */ |
|---|
| 59 | | IWriter makeWriter (PathView path, DataSet dataset = null, WriterMethod method = WriterMethod.Unspecified) { |
|---|
| | 73 | IWriter makeWriter (PathView path, DataSet dataset = null, WriterMethod method = WriterMethod.Unspecified) |
|---|
| | 74 | { |
|---|
| 60 | 75 | void throwMTErr (char[] msg, Exception exc = new MTException) { |
|---|
| 61 | 76 | logger.error (msg); |
|---|
| … | … | |
| 71 | 86 | else if (method == WriterMethod.Text) return new TextWriter (path, dataset); |
|---|
| 72 | 87 | else if (method == WriterMethod.Both) throwMTErr ("Dual writing not supported yet!", new MTFileFormatException); |
|---|
| | 88 | else debug throwMTErr ("Bad value of method", new MTFileFormatException); |
|---|
| 73 | 89 | } |
|---|
| 74 | 90 | |
|---|
| … | … | |
| 93 | 109 | * |
|---|
| 94 | 110 | * Files are only actually open for writing while the write() method is running. |
|---|
| | 111 | * |
|---|
| | 112 | * Throws: |
|---|
| | 113 | * $(TABLE |
|---|
| | 114 | * $(TR $(TH Exception) $(TH Thrown when)) |
|---|
| | 115 | * $(TR $(TD MTNoDataSetException) $(TD No dataset is available to write from)) |
|---|
| | 116 | * $(TR $(TD MTFileIOException) $(TD An error occurs while attemting to write the file)) |
|---|
| | 117 | * $(TR $(TD MTException) $(TD An unexpected error occurs)) |
|---|
| | 118 | * ) |
|---|
| | 119 | * Note that all exceptions extend MTException; unlike Reader exceptions don't block further calls. |
|---|
| 95 | 120 | */ |
|---|
| 96 | | scope class TextWriter : IWriter |
|---|
| | 121 | class TextWriter : IWriter |
|---|
| 97 | 122 | { |
|---|
| 98 | 123 | //BEGIN DATA |
|---|
| … | … | |
| 113 | 138 | DataSet _dataset; |
|---|
| 114 | 139 | |
|---|
| 115 | | PathView path; |
|---|
| | 140 | PathView _path; |
|---|
| 116 | 141 | //END DATA |
|---|
| 117 | 142 | |
|---|
| 118 | 143 | //BEGIN CTOR / DTOR |
|---|
| 119 | | /** Tries to open file path for writing. |
|---|
| | 144 | /** Prepares to open file path for writing. |
|---|
| | 145 | * |
|---|
| | 146 | * The call doesn't actually execute any code so cannot fail (unless out of memory). |
|---|
| 120 | 147 | * |
|---|
| 121 | 148 | * Params: |
|---|
| … | … | |
| 125 | 152 | * data into it. |
|---|
| 126 | 153 | */ |
|---|
| 127 | | public this (char[] _path, DataSet ds = null) { |
|---|
| 128 | | this (new FilePath (_path), ds); |
|---|
| | 154 | public this (char[] path, DataSet ds = null) { |
|---|
| | 155 | this (new FilePath (path), ds); |
|---|
| 129 | 156 | } |
|---|
| 130 | 157 | /** ditto */ |
|---|
| 131 | | public this (PathView _path, DataSet ds = null) { |
|---|
| 132 | | path = _path; |
|---|
| | 158 | public this (PathView path, DataSet ds = null) { |
|---|
| | 159 | _path = path; |
|---|
| 133 | 160 | _dataset = ds; |
|---|
| 134 | 161 | } |
|---|
| … | … | |
| 142 | 169 | * multiple DataSets into one file without firstly merging them. Note that this behaviour may |
|---|
| 143 | 170 | * be changed when binary support is added. |
|---|
| 144 | | * |
|---|
| 145 | | * Throws: |
|---|
| 146 | | * MTNoDataSetException if the dataset is null, |
|---|
| 147 | | * MTFileIOException if a file IO error occurs, |
|---|
| 148 | | * MTException on any other exception (unexpected). |
|---|
| 149 | 171 | */ |
|---|
| 150 | 172 | public void write () |
|---|
| 151 | 173 | { |
|---|
| 152 | | if (!_dataset) throw new MTNoDataSetException ("write(): Dataset needed to write from!"); |
|---|
| | 174 | if (!_dataset) throwMTErr ("write(): no Dataset available to write from!", new MTNoDataSetException ()); |
|---|
| 153 | 175 | |
|---|
| 154 | 176 | try { |
|---|
| … | … | |
| 157 | 179 | |
|---|
| 158 | 180 | // Open a conduit on the file: |
|---|
| 159 | | conduit = new FileConduit (path, FileConduit.WriteCreate); |
|---|
| | 181 | conduit = new FileConduit (_path, FileConduit.WriteCreate); |
|---|
| 160 | 182 | scope(exit) conduit.close(); |
|---|
| 161 | 183 | |
|---|
| r10 |
r11 |
|
| 2 | 2 | */ |
|---|
| 3 | 3 | module test.mdeTest; |
|---|
| 4 | | |
|---|
| 5 | | // Define this to run unittests: |
|---|
| 6 | | debug=mdeUnitTest; |
|---|
| 7 | 4 | |
|---|
| 8 | 5 | // This module should import all mde modules containing unittests: |
|---|