1 2 3 // Copyright Ferdinand Majerech 2011. 4 // Distributed under the Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 module dyaml.escapes; 9 10 package: 11 12 import std.meta : AliasSeq; 13 alias escapes = AliasSeq!('0', 'a', 'b', 't', '\t', 'n', 'v', 'f', 'r', 'e', ' ', 14 '/', '\"', '\\', 'N', '_', 'L', 'P'); 15 16 /// YAML hex codes specifying the length of the hex number. 17 alias escapeHexCodeList = AliasSeq!('x', 'u', 'U'); 18 19 /// Convert a YAML escape to a dchar. 20 dchar fromEscape(dchar escape) @safe pure nothrow @nogc 21 { 22 switch(escape) 23 { 24 case '0': return '\0'; 25 case 'a': return '\x07'; 26 case 'b': return '\x08'; 27 case 't': return '\x09'; 28 case '\t': return '\x09'; 29 case 'n': return '\x0A'; 30 case 'v': return '\x0B'; 31 case 'f': return '\x0C'; 32 case 'r': return '\x0D'; 33 case 'e': return '\x1B'; 34 case '/': return '/'; 35 case ' ': return '\x20'; 36 case '\"': return '\"'; 37 case '\\': return '\\'; 38 case 'N': return '\x85'; //'\u0085'; 39 case '_': return '\xA0'; 40 case 'L': return '\u2028'; 41 case 'P': return '\u2029'; 42 default: assert(false, "No such YAML escape"); 43 } 44 } 45 46 /** 47 * Convert a dchar to a YAML escape. 48 * 49 * Params: 50 * value = The possibly escapable character. 51 * 52 * Returns: 53 * If the character passed as parameter can be escaped, returns the matching 54 * escape, otherwise returns a null character. 55 */ 56 dchar toEscape(dchar value) @safe pure nothrow @nogc 57 { 58 switch(value) 59 { 60 case '\0': return '0'; 61 case '\x07': return 'a'; 62 case '\x08': return 'b'; 63 case '\x09': return 't'; 64 case '\x0A': return 'n'; 65 case '\x0B': return 'v'; 66 case '\x0C': return 'f'; 67 case '\x0D': return 'r'; 68 case '\x1B': return 'e'; 69 case '\"': return '\"'; 70 case '\\': return '\\'; 71 case '\xA0': return '_'; 72 case '\x85': return 'N'; 73 case '\u2028': return 'L'; 74 case '\u2029': return 'P'; 75 default: return 0; 76 } 77 } 78 79 /// Get the length of a hexadecimal number determined by its hex code. 80 /// 81 /// Need a function as associative arrays don't work with @nogc. 82 /// (And this may be even faster with a function.) 83 uint escapeHexLength(dchar hexCode) @safe pure nothrow @nogc 84 { 85 switch(hexCode) 86 { 87 case 'x': return 2; 88 case 'u': return 4; 89 case 'U': return 8; 90 default: assert(false, "No such YAML hex code"); 91 } 92 } 93 94 // Issue #302: Support optional escaping of forward slashes in string 95 // for JSON compatibility 96 @safe unittest 97 { 98 import dyaml.loader : Loader; 99 100 const str = `{ 101 "forward/slashes": "can\/be\/optionally\/escaped" 102 }`; 103 104 auto node = Loader.fromString(str).load(); 105 assert(node["forward/slashes"] == "can/be/optionally/escaped"); 106 }