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 package:
29 // Position in a YAML stream, used for error messages.
30 struct Mark
31 {
32     package:
33         /// Line number.
34         ushort line_;
35         /// Column number.
36         ushort column_;
37 
38     public:
39         /// Construct a Mark with specified line and column in the file.
40         this(const uint line, const uint column) @safe pure nothrow @nogc
41         {
42             line_   = cast(ushort)min(ushort.max, line);
43             // This *will* overflow on extremely wide files but saves CPU time
44             // (mark ctor takes ~5% of time)
45             column_ = cast(ushort)column;
46         }
47 
48         /// Get a string representation of the mark.
49         string toString() @safe pure nothrow const
50         {
51             // Line/column numbers start at zero internally, make them start at 1.
52             static string clamped(ushort v) @safe pure nothrow
53             {
54                 return text(v + 1, v == ushort.max ? " or higher" : "");
55             }
56             return "line " ~ clamped(line_) ~ ",column " ~ clamped(column_);
57         }
58 }
59 
60 static assert(Mark.sizeof == 4, "Unexpected Mark size");
61 
62 // A struct storing parameters to the MarkedYAMLException constructor.
63 struct MarkedYAMLExceptionData
64 {
65     // Context of the error.
66     string context;
67     // Position of the context in a YAML buffer.
68     Mark contextMark;
69     // The error itself.
70     string problem;
71     // Position if the error.
72     Mark problemMark;
73 }
74 
75 // Base class of YAML exceptions with marked positions of the problem.
76 abstract class MarkedYAMLException : YAMLException
77 {
78     // Construct a MarkedYAMLException with specified context and problem.
79     this(string context, const Mark contextMark, string problem, const Mark problemMark,
80          string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
81     {
82         const msg = context ~ '\n' ~
83                     (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~
84                     problem ~ '\n' ~ problemMark.toString() ~ '\n';
85         super(msg, file, line);
86     }
87 
88     // Construct a MarkedYAMLException with specified problem.
89     this(string problem, const Mark problemMark,
90          string file = __FILE__, size_t line = __LINE__)
91         @safe pure nothrow
92     {
93         super(problem ~ '\n' ~ problemMark.toString(), file, line);
94     }
95 
96     /// Construct a MarkedYAMLException from a struct storing constructor parameters.
97     this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
98     {
99         with(data) this(context, contextMark, problem, problemMark);
100     }
101 }
102 
103 // Constructors of YAML exceptions are mostly the same, so we use a mixin.
104 //
105 // See_Also: YAMLException
106 template ExceptionCtors()
107 {
108     public this(string msg, string file = __FILE__, size_t line = __LINE__)
109         @safe pure nothrow
110     {
111         super(msg, file, line);
112     }
113 }
114 
115 // Constructors of marked YAML exceptions are mostly the same, so we use a mixin.
116 //
117 // See_Also: MarkedYAMLException
118 template MarkedExceptionCtors()
119 {
120     public:
121         this(string context, const Mark contextMark, string problem,
122              const Mark problemMark, string file = __FILE__, size_t line = __LINE__)
123             @safe pure nothrow
124         {
125             super(context, contextMark, problem, problemMark,
126                   file, line);
127         }
128 
129         this(string problem, const Mark problemMark,
130              string file = __FILE__, size_t line = __LINE__)
131             @safe pure nothrow
132         {
133             super(problem, problemMark, file, line);
134         }
135 
136         this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
137         {
138             super(data);
139         }
140 }