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