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