1 module dyaml.stream; 2 3 enum BOM 4 { 5 UTF8, /// UTF-8 6 UTF16LE, /// UTF-16 Little Endian 7 UTF16BE, /// UTF-16 Big Endian 8 UTF32LE, /// UTF-32 Little Endian 9 UTF32BE, /// UTF-32 Big Endian 10 } 11 12 import std.system; 13 14 private enum int NBOMS = 5; 15 immutable Endian[NBOMS] BOMEndian = 16 [ 17 std.system.endian, 18 Endian.littleEndian, Endian.bigEndian, 19 Endian.littleEndian, Endian.bigEndian 20 ]; 21 22 immutable ubyte[][NBOMS] ByteOrderMarks = 23 [ 24 [0xEF, 0xBB, 0xBF], 25 [0xFF, 0xFE], 26 [0xFE, 0xFF], 27 [0xFF, 0xFE, 0x00, 0x00], 28 [0x00, 0x00, 0xFE, 0xFF] 29 ]; 30 31 interface YStream 32 { 33 void writeExact(const void* buffer, size_t size); 34 size_t write(const(ubyte)[] buffer); 35 size_t write(const(char)[] str); 36 void flush(); 37 @property bool writeable(); 38 } 39 40 class YMemoryStream : YStream 41 { 42 ubyte[] data; 43 44 void writeExact(const void* buffer, size_t size) 45 { 46 data ~= cast(ubyte[])buffer[0 .. size]; 47 } 48 49 size_t write(const(ubyte)[] buffer) 50 { 51 data ~= buffer; 52 return buffer.length; 53 } 54 55 size_t write(const(char)[] str) 56 { 57 return write(cast(const(ubyte)[])str); 58 } 59 60 void flush() {} 61 62 @property bool writeable() { return true; } 63 } 64 65 class YFile : YStream 66 { 67 static import std.stdio; 68 std.stdio.File file; 69 70 this(string fn) 71 { 72 this.file = std.stdio.File(fn, "w"); 73 } 74 75 this(std.stdio.File file) 76 { 77 this.file = file; 78 } 79 80 unittest 81 { 82 import std.stdio : stdout; 83 auto stream = new YFile(stdout); 84 stream.write("Test writing to stdout through YFile stream\n"); 85 } 86 87 void writeExact(const void* buffer, size_t size) 88 { 89 this.file.rawWrite(cast(const) buffer[0 .. size]); 90 } 91 92 size_t write(const(ubyte)[] buffer) 93 { 94 this.file.rawWrite(buffer); 95 return buffer.length; 96 } 97 98 size_t write(const(char)[] str) 99 { 100 return write(cast(const(ubyte)[])str); 101 } 102 103 void flush() 104 { 105 this.file.flush(); 106 } 107 108 @property bool writeable() { return true; } 109 } 110 111 unittest 112 { 113 import dyaml.dumper, dyaml.loader, dyaml.node; 114 import std.file : readText, remove; 115 116 char[] test = ("Hello World : [Hello, World]\n" ~ 117 "Answer: 42").dup; 118 //Read the input. 119 Node expected = Loader.fromString(test).load(); 120 assert(expected["Hello World"][0] == "Hello"); 121 assert(expected["Hello World"][1] == "World"); 122 assert(expected["Answer"].as!int == 42); 123 124 //Dump the loaded document to output.yaml. 125 Dumper("output.yaml").dump(expected); 126 127 // Load the file and verify that it was saved correctly. 128 Node actual = Loader("output.yaml").load(); 129 assert(actual["Hello World"][0] == "Hello"); 130 assert(actual["Hello World"][1] == "World"); 131 assert(actual["Answer"].as!int == 42); 132 assert(actual == expected); 133 134 // Clean up. 135 remove("output.yaml"); 136 }