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 }