PageRenderTime 61ms CodeModel.GetById 46ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 1ms

/src/wrappers/glib/library/data_types/g_error.e

http://github.com/tybor/Liberty
Specman e | 347 lines | 81 code | 68 blank | 198 comment | 4 complexity | 525ea3537dfb3a47708154b456a58ad7 MD5 | raw file
  1indexing
  2	description: "G_ERROR - information about an error that has occurred."
  3	copyright: "[
  4					Copyright (C) 2006 eiffel-libraries team, GTK+ team
  5					
  6					This library is free software; you can redistribute it and/or
  7					modify it under the terms of the GNU Lesser General Public License
  8					as published by the Free Software Foundation; either version 2.1 of
  9					the License, or (at your option) any later version.
 10					
 11					This library is distributed in the hope that it will be useful, but
 12					WITHOUT ANY WARRANTY; without even the implied warranty of
 13					MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14					Lesser General Public License for more details.
 15
 16					You should have received a copy of the GNU Lesser General Public
 17					License along with this library; if not, write to the Free Software
 18					Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19					02110-1301 USA
 20					]"
 21					
 22
 23class G_ERROR 
 24	-- The G_ERROR object contains information about an error that has
 25	-- occurred.
 26
 27	-- GLib provides a standard method of reporting errors from a called
 28	-- function to the calling code. (This is the same problem solved by
 29	-- exceptions in other languages.) It's important to understand that this
 30	-- method is both a data type (the G_ERROR object) and a set of rules. If
 31	-- you use G_ERROR incorrectly, then your code will not properly
 32	-- interoperate with other code that use G_ERROR, and users of your API
 33	-- will probably get confused.
 34
 35	-- First and foremost: G_ERROR should only be used to report recoverable
 36	-- runtime errors, never to report programming errors. If the programmer
 37	-- has screwed up, then you should use the facilities offered by
 38	-- GLIB_MESSAGE_LOGGING.
 39					
 40	-- Examples of recoverable runtime errors are "file not found" or "failed
 41	-- to parse input." Examples of programming errors are "NULL passed to
 42	-- strcmp()" or "attempted to free the same pointer twice." These two kinds
 43	-- of errors are fundamentally different: runtime errors should be handled
 44	-- or reported to the user, programming errors should be eliminated by
 45	-- fixing the bug in the program. This is why most functions in GLib and
 46	-- GTK+ do not use G_ERROR.
 47
 48	-- Classes having features that can fail will insert SHARED_G_ERROR; each
 49	-- feature whose invocation can fail will change `error' and
 50	-- `is_successful'.
 51	
 52	-- Use 'matches' to see if the error
 53	-- matches a given domain and code
 54	
 55	-- (TODO) 'propagate' copies an error into an error location (so the calling
 56	-- function will receive it)
 57	
 58	-- 'clear' clears an error location by freeing the error and resetting
 59	-- the location to NULL. 
 60	
 61	-- To display an error to the user,
 62	-- simply display 'message', perhaps along with
 63	-- additional context known only to the calling function
 64	-- (the file being opened, or whatever -- though in the
 65	-- g_file_get_contents() case, error->message already
 66	-- contains a filename).
 67
 68	-- When implementing a function that can report errors,
 69	-- the basic tool is (TODO) 'set'. Typically, if a fatal
 70	-- error occurs you want to (TODO) 'set_error', then return
 71	-- immediately.	
 72	
 73	-- TODO: Eiffellize. Things are somewhat more complicated if you yourself
 74	-- call another function that can report a GError. If the
 75	-- sub-function indicates fatal errors in some way other
 76	-- than reporting a GError, such as by returning TRUE on
 77	-- success, you can simply do the following:
 78
 79	-- gboolean
 80	-- my_function_that_can_fail (GError **err)
 81	-- {
 82	--   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 83
 84	--   if (!sub_function_that_can_fail (err))
 85	--     {
 86	--        /* assert that error was set by the sub-function */
 87	--        g_assert (err == NULL || *err != NULL);  
 88	--        return FALSE;
 89	--     }
 90
 91	--   /* otherwise continue, no error occurred */
 92	--   g_assert (err == NULL || *err == NULL);
 93	-- }
 94
 95	-- If the sub-function does not indicate errors other than
 96	-- by reporting a GError, you need to create a temporary
 97	-- GError since the passed-in one may be
 98	-- NULL. g_propagate_error() is intended for use in this
 99	-- case.
100
101	-- gboolean
102	-- my_function_that_can_fail (GError **err)
103	-- {
104	--   GError *tmp_error;
105
106	--   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
107
108	--   tmp_error = NULL;
109	--   sub_function_that_can_fail (&tmp_error);
110
111	--   if (tmp_error != NULL)
112	--     {
113	--        /* store tmp_error in err, if err != NULL,
114	--         * otherwise call g_error_free() on tmp_error 
115	--         */
116	--        g_propagate_error (err, tmp_error);
117	--        return FALSE;
118	--     }
119
120	--   /* otherwise continue, no error occurred */
121	-- }
122
123	-- Error pileups are always a bug. For example, this code is incorrect:
124
125	-- gboolean
126	-- my_function_that_can_fail (GError **err)
127	-- {
128	--   GError *tmp_error;
129
130	--   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
131
132	--   tmp_error = NULL;
133	--   sub_function_that_can_fail (&tmp_error);
134	--   other_function_that_can_fail (&tmp_error);
135
136	--   if (tmp_error != NULL)
137	--     {
138	--        g_propagate_error (err, tmp_error);
139	--        return FALSE;
140	--     }
141	-- }
142
143	-- tmp_error should be checked immediately after
144	-- sub_function_that_can_fail(), and either cleared or
145	-- propagated upward. The rule is: after each error, you
146	-- must either handle the error, or return it to the
147	-- calling function. Note that passing NULL for the error
148	-- location is the equivalent of handling an error by
149	-- always doing nothing about it. So the following code is
150	-- fine, assuming errors in sub_function_that_can_fail()
151	-- are not fatal to my_function_that_can_fail():
152
153	-- gboolean
154	-- my_function_that_can_fail (GError **err)
155	-- {
156	--   GError *tmp_error;
157
158	--   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
159
160	--   sub_function_that_can_fail (NULL); /* ignore errors */
161
162	--   tmp_error = NULL;
163	--   other_function_that_can_fail (&tmp_error);
164
165	--   if (tmp_error != NULL)
166	--     {
167	--        g_propagate_error (err, tmp_error);
168	--        return FALSE;
169	--     }
170	-- }
171
172	-- Note that passing NULL for the error location ignores
173	-- errors; it's equivalent to try {
174	-- sub_function_that_can_fail(); } catch (...) {} in
175	-- C++. It does not mean to leave errors unhandled; it
176	-- means to handle them by doing nothing.
177
178	-- Error domains and codes are conventionally named as follows:
179
180	-- * The error domain is called
181	-- <NAMESPACE>_<MODULE>_ERROR, for example G_EXEC_ERROR
182	-- or G_THREAD_ERROR.
183					
184	-- * The error codes are in an enumeration called
185	-- <Namespace><Module>Error; for example, GThreadError
186	-- or GSpawnError.
187
188	-- * Members of the error code enumeration are called
189	-- <NAMESPACE>_<MODULE>_ERROR_<CODE>, for example
190	-- G_SPAWN_ERROR_FORK or G_THREAD_ERROR_AGAIN.  *
191
192	-- If there's a "generic" or "unknown" error code for
193	-- unrecoverable errors it doesn't make sense to
194	-- distinguish with specific codes, it should be called
195	-- <NAMESPACE>_<MODULE>_ERROR_FAILED, for example
196	-- G_SPAWN_ERROR_FAILED or G_THREAD_ERROR_FAILED.
197
198	-- Summary of rules for use of GError:
199
200	-- * Do not report programming errors via GError.
201
202	-- * The last argument of a function that returns an
203	-- error should be a location where a GError can be
204	-- placed (i.e. "GError** error"). If GError is used
205	-- with varargs, the GError** should be the last
206	-- argument before the "...".
207
208	-- * The caller may pass NULL for the GError** if they
209	-- are not interested in details of the exact error
210	-- that occurred.
211
212	-- * If NULL is passed for the GError** argument, then
213	-- errors should not be returned to the caller, but
214	-- your function should still abort and return if an
215	-- error occurs. That is, control flow should not be
216	-- affected by whether the caller wants to get a
217	-- GError.
218					
219	-- * If a GError is reported, then your function by
220	-- definition had a fatal failure and did not complete
221	-- whatever it was supposed to do. If the failure was
222	-- not fatal, then you handled it and you should not
223	-- report it. If it was fatal, then you must report it
224	-- and discontinue whatever you were doing immediately.
225					
226	-- * A GError* must be initialized to NULL before
227	-- passing its address to a function that can report
228	-- errors.
229					
230	-- * "Piling up" errors is always a bug. That is, if
231	-- you assign a new GError to a GError* that is
232	-- non-NULL, thus overwriting the previous error, it
233	-- indicates that you should have aborted the operation
234	-- instead of continuing. If you were able to continue,
235	-- you should have cleared the previous error with
236	-- g_clear_error(). g_set_error() will complain if you
237	-- pile up errors.  *
238
239	-- By convention, if you return a boolean value
240	-- indicating success then TRUE means success and FALSE
241	-- means failure. If FALSE is returned, the error must
242	-- be set to a non-NULL value.
243				
244	-- * A NULL return value is also frequently used to
245	-- mean that an error occurred. You should make clear
246	-- in your documentation whether NULL is a valid return
247	-- value in non-error cases; if NULL is a valid value,
248	-- then users must check whether an error was returned
249	-- to see if the function succeeded.
250					
251	-- * When implementing a function that can report
252	-- errors, you may want to add a check at the top of
253	-- your function that the error return location is
254	-- either NULL or contains a NULL error
255	-- (e.g. g_return_if_fail (error == NULL || *error ==
256	-- NULL);).
257
258inherit
259	C_STRUCT
260		redefine free_handle
261		end
262
263insert
264	GERROR_EXTERNALS
265	GERROR_STRUCT
266
267creation
268	make, empty, from_external_pointer
269
270feature {} -- Creation
271
272	make (a_domain: G_QUARK; a_code: INTEGER; a_message: STRING) is
273			-- Creates a new G_ERROR
274		do
275			from_external_pointer (g_error_new_literal (a_domain.quark, a_code, a_message.to_external))
276		ensure not_null: handle.is_not_null
277		end
278
279	empty is
280		do
281			-- This feature is empty by design. No initialization is
282			-- needed because the feature that will return an error will
283			-- allocate a GError C structure, changing the value of
284			-- handle
285		end
286	
287feature -- Access
288	is_set: BOOLEAN is
289		-- Has Current been set? Usually it is set by a call to a C library
290	do
291		Result := handle.is_not_null
292	end
293
294	domain: G_QUARK is
295		-- The module whewre the error-reporting feature is located in. 
296		require is_set
297		do
298			Result.set_quark (gerror_struct_get_domain (handle))
299		end 
300
301	code: INTEGER is
302		-- The specific error that occurred encoded as a programmer-defined
303		-- constant.
304		require is_set
305		do
306			Result := gerror_struct_get_code (handle)
307		end
308
309	message: STRING is
310		-- a user-readable error message with as many details as possible. 
311		require is_set
312		local
313			ptr: POINTER
314		do
315			ptr := gerror_struct_get_message (handle)
316			if ptr.is_not_null then
317				create Result.from_external_copy (ptr)
318			end
319		end
320	
321feature -- Comparison
322
323	matches (a_domain: G_QUARK; a_code: INTEGER): BOOLEAN is
324			-- Does Current G_ERROR matches 'a_domain' and 'a_code'?
325		require is_set
326		do
327			Result := g_error_matches (handle, a_domain.quark, a_code).to_boolean
328		end
329
330feature -- Disposing
331
332	dispose is
333			-- Frees a G_ERROR and associated resources.
334		do
335			if is_set then
336				free_handle
337			end
338		end
339
340	free_handle is
341		require is_set
342		do
343			g_error_free (handle)
344			handle := default_pointer
345		end
346
347end