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 17 /// Base class for all exceptions thrown by D:YAML. 18 class YAMLException : Exception 19 { 20 /// Construct a YAMLException with specified message and position where it was thrown. 21 public this(string msg, string file = __FILE__, size_t line = __LINE__) 22 @safe pure nothrow @nogc 23 { 24 super(msg, file, line); 25 } 26 } 27 28 /// Position in a YAML stream, used for error messages. 29 struct Mark 30 { 31 package: 32 /// File name. 33 string name_; 34 /// Line number. 35 ushort line_; 36 /// Column number. 37 ushort column_; 38 39 public: 40 /// Construct a Mark with specified line and column in the file. 41 this(string name, const uint line, const uint column) @safe pure nothrow @nogc 42 { 43 name_ = name; 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 file name. 51 @property string name() @safe pure nothrow @nogc const 52 { 53 return name_; 54 } 55 56 /// Get a line number. 57 @property ushort line() @safe pure nothrow @nogc const 58 { 59 return line_; 60 } 61 62 /// Get a column number. 63 @property ushort column() @safe pure nothrow @nogc const 64 { 65 return column_; 66 } 67 68 /// Duplicate a mark 69 Mark dup () const scope @safe pure nothrow 70 { 71 return Mark(this.name_.idup, this.line_, this.column_); 72 } 73 74 /// Get a string representation of the mark. 75 string toString() const scope @safe pure nothrow 76 { 77 // Line/column numbers start at zero internally, make them start at 1. 78 static string clamped(ushort v) @safe pure nothrow 79 { 80 return text(v + 1, v == ushort.max ? " or higher" : ""); 81 } 82 return "file " ~ name_ ~ ",line " ~ clamped(line_) ~ ",column " ~ clamped(column_); 83 } 84 } 85 86 // Base class of YAML exceptions with marked positions of the problem. 87 abstract class MarkedYAMLException : YAMLException 88 { 89 /// Position of the error. 90 Mark mark; 91 92 // Construct a MarkedYAMLException with specified context and problem. 93 this(string context, scope const Mark contextMark, 94 string problem, scope const Mark problemMark, 95 string file = __FILE__, size_t line = __LINE__) @safe pure nothrow 96 { 97 const msg = context ~ '\n' ~ 98 (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~ 99 problem ~ '\n' ~ problemMark.toString() ~ '\n'; 100 super(msg, file, line); 101 mark = problemMark.dup; 102 } 103 104 // Construct a MarkedYAMLException with specified problem. 105 this(string problem, scope const Mark problemMark, 106 string file = __FILE__, size_t line = __LINE__) 107 @safe pure nothrow 108 { 109 super(problem ~ '\n' ~ problemMark.toString(), file, line); 110 mark = problemMark.dup; 111 } 112 113 /// Construct a MarkedYAMLException from a struct storing constructor parameters. 114 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 115 { 116 with(data) this(context, contextMark, problem, problemMark); 117 } 118 } 119 120 package: 121 // A struct storing parameters to the MarkedYAMLException constructor. 122 struct MarkedYAMLExceptionData 123 { 124 // Context of the error. 125 string context; 126 // Position of the context in a YAML buffer. 127 Mark contextMark; 128 // The error itself. 129 string problem; 130 // Position if the error. 131 Mark problemMark; 132 } 133 134 // Constructors of YAML exceptions are mostly the same, so we use a mixin. 135 // 136 // See_Also: YAMLException 137 template ExceptionCtors() 138 { 139 public this(string msg, string file = __FILE__, size_t line = __LINE__) 140 @safe pure nothrow 141 { 142 super(msg, file, line); 143 } 144 } 145 146 // Constructors of marked YAML exceptions are mostly the same, so we use a mixin. 147 // 148 // See_Also: MarkedYAMLException 149 template MarkedExceptionCtors() 150 { 151 public: 152 this(string context, const Mark contextMark, string problem, 153 const Mark problemMark, string file = __FILE__, size_t line = __LINE__) 154 @safe pure nothrow 155 { 156 super(context, contextMark, problem, problemMark, 157 file, line); 158 } 159 160 this(string problem, const Mark problemMark, 161 string file = __FILE__, size_t line = __LINE__) 162 @safe pure nothrow 163 { 164 super(problem, problemMark, file, line); 165 } 166 167 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 168 { 169 super(data); 170 } 171 }