1 2 // Copyright Ferdinand Majerech 2011. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 ///Exceptions thrown by D:YAML and _exception related code. 8 module dyaml.exception; 9 10 11 import std.algorithm; 12 import std.array; 13 import std..string; 14 import std.conv; 15 16 alias to!string str; 17 18 19 /// Base class for all exceptions thrown by D:YAML. 20 class YAMLException : Exception 21 { 22 /// Construct a YAMLException with specified message and position where it was thrown. 23 public this(string msg, string file = __FILE__, size_t line = __LINE__) 24 @safe pure nothrow 25 { 26 super(msg, file, line); 27 } 28 } 29 30 package: 31 // Position in a YAML stream, used for error messages. 32 struct Mark 33 { 34 package: 35 /// Line number. 36 ushort line_; 37 /// Column number. 38 ushort column_; 39 40 public: 41 /// Construct a Mark with specified line and column in the file. 42 this(const uint line, const uint column) @safe pure nothrow @nogc 43 { 44 line_ = cast(ushort)min(ushort.max, line); 45 // This *will* overflow on extremely wide files but saves CPU time 46 // (mark ctor takes ~5% of time) 47 column_ = cast(ushort)column; 48 } 49 50 /// Get a string representation of the mark. 51 string toString() @safe pure nothrow const 52 { 53 // Line/column numbers start at zero internally, make them start at 1. 54 static string clamped(ushort v) @safe pure nothrow 55 { 56 return str(v + 1) ~ (v == ushort.max ? " or higher" : ""); 57 } 58 return "line " ~ clamped(line_) ~ ",column " ~ clamped(column_); 59 } 60 } 61 62 static assert(Mark.sizeof == 4, "Unexpected Mark size"); 63 64 // A struct storing parameters to the MarkedYAMLException constructor. 65 struct MarkedYAMLExceptionData 66 { 67 // Context of the error. 68 string context; 69 // Position of the context in a YAML buffer. 70 Mark contextMark; 71 // The error itself. 72 string problem; 73 // Position if the error. 74 Mark problemMark; 75 } 76 77 // Base class of YAML exceptions with marked positions of the problem. 78 abstract class MarkedYAMLException : YAMLException 79 { 80 // Construct a MarkedYAMLException with specified context and problem. 81 this(string context, const Mark contextMark, string problem, const Mark problemMark, 82 string file = __FILE__, size_t line = __LINE__) @safe pure nothrow 83 { 84 const msg = context ~ '\n' ~ 85 (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~ 86 problem ~ '\n' ~ problemMark.toString() ~ '\n'; 87 super(msg, file, line); 88 } 89 90 // Construct a MarkedYAMLException with specified problem. 91 this(string problem, const Mark problemMark, 92 string file = __FILE__, size_t line = __LINE__) 93 @safe pure nothrow 94 { 95 super(problem ~ '\n' ~ problemMark.toString(), file, line); 96 } 97 98 /// Construct a MarkedYAMLException from a struct storing constructor parameters. 99 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 100 { 101 with(data) this(context, contextMark, problem, problemMark); 102 } 103 } 104 105 // Constructors of YAML exceptions are mostly the same, so we use a mixin. 106 // 107 // See_Also: YAMLException 108 template ExceptionCtors() 109 { 110 public this(string msg, string file = __FILE__, size_t line = __LINE__) 111 @safe pure nothrow 112 { 113 super(msg, file, line); 114 } 115 } 116 117 // Constructors of marked YAML exceptions are mostly the same, so we use a mixin. 118 // 119 // See_Also: MarkedYAMLException 120 template MarkedExceptionCtors() 121 { 122 public: 123 this(string context, const Mark contextMark, string problem, 124 const Mark problemMark, string file = __FILE__, size_t line = __LINE__) 125 @safe pure nothrow 126 { 127 super(context, contextMark, problem, problemMark, 128 file, line); 129 } 130 131 this(string problem, const Mark problemMark, 132 string file = __FILE__, size_t line = __LINE__) 133 @safe pure nothrow 134 { 135 super(problem, problemMark, file, line); 136 } 137 138 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 139 { 140 super(data); 141 } 142 }