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 // A struct storing parameters to the MarkedYAMLException constructor.
61 struct MarkedYAMLExceptionData
62 {
63     // Context of the error.
64     string context;
65     // Position of the context in a YAML buffer.
66     Mark contextMark;
67     // The error itself.
68     string problem;
69     // Position if the error.
70     Mark problemMark;
71 }
72 
73 // Base class of YAML exceptions with marked positions of the problem.
74 abstract class MarkedYAMLException : YAMLException
75 {
76     // Construct a MarkedYAMLException with specified context and problem.
77     this(string context, const Mark contextMark, string problem, const Mark problemMark,
78          string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
79     {
80         const msg = context ~ '\n' ~
81                     (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~
82                     problem ~ '\n' ~ problemMark.toString() ~ '\n';
83         super(msg, file, line);
84     }
85 
86     // Construct a MarkedYAMLException with specified problem.
87     this(string problem, const Mark problemMark,
88          string file = __FILE__, size_t line = __LINE__)
89         @safe pure nothrow
90     {
91         super(problem ~ '\n' ~ problemMark.toString(), file, line);
92     }
93 
94     /// Construct a MarkedYAMLException from a struct storing constructor parameters.
95     this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
96     {
97         with(data) this(context, contextMark, problem, problemMark);
98     }
99 }
100 
101 // Constructors of YAML exceptions are mostly the same, so we use a mixin.
102 //
103 // See_Also: YAMLException
104 template ExceptionCtors()
105 {
106     public this(string msg, string file = __FILE__, size_t line = __LINE__)
107         @safe pure nothrow
108     {
109         super(msg, file, line);
110     }
111 }
112 
113 // Constructors of marked YAML exceptions are mostly the same, so we use a mixin.
114 //
115 // See_Also: MarkedYAMLException
116 template MarkedExceptionCtors()
117 {
118     public:
119         this(string context, const Mark contextMark, string problem,
120              const Mark problemMark, string file = __FILE__, size_t line = __LINE__)
121             @safe pure nothrow
122         {
123             super(context, contextMark, problem, problemMark,
124                   file, line);
125         }
126 
127         this(string problem, const Mark problemMark,
128              string file = __FILE__, size_t line = __LINE__)
129             @safe pure nothrow
130         {
131             super(problem, problemMark, file, line);
132         }
133 
134         this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
135         {
136             super(data);
137         }
138 }