1/*
2 * PROGRAM: Firebird exceptions classes
3 * MODULE: StatusHolder.h
4 * DESCRIPTION: Firebird's exception classes
5 *
6 * The contents of this file are subject to the Initial
7 * Developer's Public License Version 1.0 (the "License");
8 * you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
11 *
12 * Software distributed under the License is distributed AS IS,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied.
14 * See the License for the specific language governing rights
15 * and limitations under the License.
16 *
17 * The Original Code was created by Vlad Khorsun
18 * for the Firebird Open Source RDBMS project.
19 *
20 * Copyright (c) 2007 Vlad Khorsun <hvlad at users.sourceforge.net>
21 * and all contributors signed below.
22 *
23 * All Rights Reserved.
24 * Contributor(s): ______________________________________.
25 *
26 *
27 */
28
29#ifndef FB_STATUS_HOLDER
30#define FB_STATUS_HOLDER
31
32#include "firebird/Provider.h"
33#include "../common/utils_proto.h"
34#include "../common/classes/ImplementHelper.h"
35#include "../common/classes/array.h"
36
37namespace Firebird {
38
39class BaseStatus : public IStatus
40{
41public:
42 // IStatus implementation
43 virtual void FB_CARG set(const ISC_STATUS* value)
44 {
45 set(fb_utils::statusLength(value), value);
46 }
47
48 virtual void FB_CARG set(unsigned int length, const ISC_STATUS* value)
49 {
50 fb_utils::copyStatus(vector, FB_NELEM(vector), value, length);
51 }
52
53 virtual void FB_CARG init()
54 {
55 fb_utils::init_status(vector);
56 }
57
58 virtual const ISC_STATUS* FB_CARG get() const
59 {
60 return vector;
61 }
62
63 virtual int FB_CARG isSuccess() const
64 {
65 return vector[1] == 0;
66 }
67
68public:
69 BaseStatus()
70 {
71 init();
72 }
73
74 void check()
75 {
76 if (!isSuccess())
77 status_exception::raise(get());
78 }
79
80private:
81 ISC_STATUS vector[40]; // FixMe - may be a kind of dynamic storage will be better?
82};
83
84class LocalStatus : public AutoIface<BaseStatus, FB_STATUS_VERSION>
85{
86public:
87 virtual void FB_CARG dispose()
88 { }
89};
90
91
92// This trivial container is used when we need to grow vector element by element w/o any conversions
93typedef HalfStaticArray<ISC_STATUS, ISC_STATUS_LENGTH> SimpleStatusVector;
94
95
96// DynamicStatusVector owns strings, contained in it
97class DynamicStatusVector
98{
99public:
100 explicit DynamicStatusVector(const ISC_STATUS* status = NULL)
101 : m_status_vector(*getDefaultMemoryPool())
102 {
103 ISC_STATUS* s = m_status_vector.getBuffer(ISC_STATUS_LENGTH);
104 fb_utils::init_status(s);
105
106 if (status)
107 {
108 save(status);
109 }
110 }
111
112 ~DynamicStatusVector()
113 {
114 clear();
115 }
116
117 ISC_STATUS save(const ISC_STATUS* status);
118 void clear();
119
120 ISC_STATUS getError() const
121 {
122 return value()[1];
123 }
124
125 const ISC_STATUS* value() const
126 {
127 return m_status_vector.begin();
128 }
129
130 bool isSuccess() const
131 {
132 return getError() == 0;
133 }
134
135 ISC_STATUS& operator[](unsigned int index)
136 {
137 return m_status_vector[index];
138 }
139
140private:
141 SimpleStatusVector m_status_vector;
142};
143
144
145class StatusHolder
146{
147public:
148 explicit StatusHolder(const ISC_STATUS* status = NULL)
149 : m_status_vector(status), m_raised(false)
150 { }
151
152 ISC_STATUS save(const ISC_STATUS* status);
153 void clear();
154 void raise();
155
156 ISC_STATUS getError()
157 {
158 return value()[1];
159 }
160
161 const ISC_STATUS* value()
162 {
163 if (m_raised) {
164 clear();
165 }
166 return m_status_vector.value();
167 }
168
169 bool isSuccess()
170 {
171 return getError() == 0;
172 }
173
174private:
175 DynamicStatusVector m_status_vector;
176 bool m_raised;
177};
178
179
180} // namespace Firebird
181
182
183#endif // FB_STATUS_HOLDER
184