1 /* Copyright (C) 2011 Wildfire Games.
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * error handling system: defines status codes, translates them to/from
25 * other schemes (e.g. errno), associates them with descriptive text,
26 * simplifies propagating errors / checking if functions failed.
29 #include "precompiled.h"
30 #include "lib/status.h"
35 #include "lib/posix/posix_errno.h"
38 static StatusDefinitionBucket
* buckets
;
40 StatusDefinitionBucket
* StatusAddDefinitions(StatusDefinitionBucket
* bucket
)
42 // insert at front of list
43 StatusDefinitionBucket
* next
= buckets
;
49 static const StatusDefinition
* DefinitionFromStatus(Status status
)
51 for(const StatusDefinitionBucket
* bucket
= buckets
; bucket
; bucket
= bucket
->next
)
53 for(size_t i
= 0; i
< bucket
->numDefinitions
; i
++)
55 if(bucket
->definitions
[i
].status
== status
)
56 return &bucket
->definitions
[i
];
64 static const StatusDefinition
* DefinitionFromErrno(int errno_equivalent
)
66 for(const StatusDefinitionBucket
* bucket
= buckets
; bucket
; bucket
= bucket
->next
)
68 for(size_t i
= 0; i
< bucket
->numDefinitions
; i
++)
70 if(bucket
->definitions
[i
].errno_equivalent
== errno_equivalent
)
71 return &bucket
->definitions
[i
];
79 wchar_t* StatusDescription(Status status
, wchar_t* buf
, size_t max_chars
)
81 const StatusDefinition
* def
= DefinitionFromStatus(status
);
84 wcscpy_s(buf
, max_chars
, def
->description
);
88 swprintf_s(buf
, max_chars
, L
"Unknown error (%lld, 0x%llX)", (long long)status
, (unsigned long long)status
);
93 int ErrnoFromStatus(Status status
)
95 const StatusDefinition
* def
= DefinitionFromStatus(status
);
96 if(def
&& def
->errno_equivalent
!= 0)
97 return def
->errno_equivalent
;
99 // the set of errnos in wposix.h doesn't have an "unknown error".
100 // we use this one as a default because it's not expected to come up often.
105 Status
StatusFromErrno()
109 const StatusDefinition
* def
= DefinitionFromErrno(errno
);
110 return def
? def
->status
: ERR::FAIL
;
114 //-----------------------------------------------------------------------------
116 static const StatusDefinition statusDefs
[] = {
118 // INFO::OK doesn't really need a string because calling StatusDescription(0)
119 // should never happen, but we'll play it safe.
120 { INFO::OK
, L
"No error reported here" },
121 { ERR::FAIL
, L
"Function failed (no details available)" },
123 { INFO::SKIPPED
, L
"Skipped (not an error)" },
124 { INFO::CANNOT_HANDLE
, L
"Cannot handle (not an error)" },
125 { INFO::ALL_COMPLETE
, L
"All complete (not an error)" },
127 { ERR::LOGIC
, L
"Logic error in code" },
128 { ERR::EXCEPTION
, L
"Caught an exception" },
129 { ERR::TIMED_OUT
, L
"Timed out" },
130 { ERR::REENTERED
, L
"Single-call function was reentered" },
131 { ERR::CORRUPTED
, L
"File/memory data is corrupted" },
132 { ERR::ABORTED
, L
"Operation aborted" },
134 { ERR::INVALID_ALIGNMENT
, L
"Invalid alignment", EINVAL
},
135 { ERR::INVALID_OFFSET
, L
"Invalid offset", EINVAL
},
136 { ERR::INVALID_HANDLE
, L
"Invalid handle", EINVAL
},
137 { ERR::INVALID_POINTER
, L
"Invalid pointer", EINVAL
},
138 { ERR::INVALID_SIZE
, L
"Invalid size", EINVAL
},
139 { ERR::INVALID_FLAG
, L
"Invalid flag", EINVAL
},
140 { ERR::INVALID_PARAM
, L
"Invalid parameter", EINVAL
},
141 { ERR::INVALID_VERSION
, L
"Invalid version", EINVAL
},
143 { ERR::AGAIN
, L
"Try again later", EAGAIN
},
144 { ERR::LIMIT
, L
"Fixed limit exceeded", E2BIG
},
145 { ERR::NOT_SUPPORTED
, L
"Function not supported", ENOSYS
},
146 { ERR::NO_MEM
, L
"Not enough memory", ENOMEM
},
148 { ERR::_1
, L
"Case 1" },
149 { ERR::_2
, L
"Case 2" },
150 { ERR::_3
, L
"Case 3" },
151 { ERR::_4
, L
"Case 4" },
152 { ERR::_5
, L
"Case 5" },
153 { ERR::_6
, L
"Case 6" },
154 { ERR::_7
, L
"Case 7" },
155 { ERR::_8
, L
"Case 8" },
156 { ERR::_9
, L
"Case 9" },
157 { ERR::_11
, L
"Case 11" },
158 { ERR::_12
, L
"Case 12" },
159 { ERR::_13
, L
"Case 13" },
160 { ERR::_14
, L
"Case 14" },
161 { ERR::_15
, L
"Case 15" },
162 { ERR::_16
, L
"Case 16" },
163 { ERR::_17
, L
"Case 17" },
164 { ERR::_18
, L
"Case 18" },
165 { ERR::_19
, L
"Case 19" },
166 { ERR::_21
, L
"Case 21" },
167 { ERR::_22
, L
"Case 22" },
168 { ERR::_23
, L
"Case 23" },
169 { ERR::_24
, L
"Case 24" },
170 { ERR::_25
, L
"Case 25" },
171 { ERR::_26
, L
"Case 26" },
172 { ERR::_27
, L
"Case 27" },
173 { ERR::_28
, L
"Case 28" },
174 { ERR::_29
, L
"Case 29" }
177 STATUS_ADD_DEFINITIONS(statusDefs
);