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 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 /// Get a string representation of the mark. 69 string toString() @safe pure nothrow const 70 { 71 // Line/column numbers start at zero internally, make them start at 1. 72 static string clamped(ushort v) @safe pure nothrow 73 { 74 return text(v + 1, v == ushort.max ? " or higher" : ""); 75 } 76 return "file " ~ name_ ~ ",line " ~ clamped(line_) ~ ",column " ~ clamped(column_); 77 } 78 } 79 80 // Base class of YAML exceptions with marked positions of the problem. 81 abstract class MarkedYAMLException : YAMLException 82 { 83 /// Position of the error. 84 Mark mark; 85 86 // Construct a MarkedYAMLException with specified context and problem. 87 this(string context, const Mark contextMark, string problem, const Mark problemMark, 88 string file = __FILE__, size_t line = __LINE__) @safe pure nothrow 89 { 90 const msg = context ~ '\n' ~ 91 (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~ 92 problem ~ '\n' ~ problemMark.toString() ~ '\n'; 93 super(msg, file, line); 94 mark = problemMark; 95 } 96 97 // Construct a MarkedYAMLException with specified problem. 98 this(string problem, const Mark problemMark, 99 string file = __FILE__, size_t line = __LINE__) 100 @safe pure nothrow 101 { 102 super(problem ~ '\n' ~ problemMark.toString(), file, line); 103 mark = problemMark; 104 } 105 106 /// Construct a MarkedYAMLException from a struct storing constructor parameters. 107 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 108 { 109 with(data) this(context, contextMark, problem, problemMark); 110 } 111 } 112 113 package: 114 // A struct storing parameters to the MarkedYAMLException constructor. 115 struct MarkedYAMLExceptionData 116 { 117 // Context of the error. 118 string context; 119 // Position of the context in a YAML buffer. 120 Mark contextMark; 121 // The error itself. 122 string problem; 123 // Position if the error. 124 Mark problemMark; 125 } 126 127 // Constructors of YAML exceptions are mostly the same, so we use a mixin. 128 // 129 // See_Also: YAMLException 130 template ExceptionCtors() 131 { 132 public this(string msg, string file = __FILE__, size_t line = __LINE__) 133 @safe pure nothrow 134 { 135 super(msg, file, line); 136 } 137 } 138 139 // Constructors of marked YAML exceptions are mostly the same, so we use a mixin. 140 // 141 // See_Also: MarkedYAMLException 142 template MarkedExceptionCtors() 143 { 144 public: 145 this(string context, const Mark contextMark, string problem, 146 const Mark problemMark, string file = __FILE__, size_t line = __LINE__) 147 @safe pure nothrow 148 { 149 super(context, contextMark, problem, problemMark, 150 file, line); 151 } 152 153 this(string problem, const Mark problemMark, 154 string file = __FILE__, size_t line = __LINE__) 155 @safe pure nothrow 156 { 157 super(problem, problemMark, file, line); 158 } 159 160 this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow 161 { 162 super(data); 163 } 164 }