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 }