VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/err/errmsg.cpp@ 106580

Last change on this file since 106580 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.5 KB
Line 
1/* $Id: errmsg.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Status code messages.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/err.h>
42#include "internal/iprt.h"
43
44#include <iprt/asm.h>
45#include <iprt/string.h>
46#include <VBox/err.h>
47
48#include <iprt/bldprog-strtab.h>
49
50
51/*********************************************************************************************************************************
52* Defined Constants And Macros *
53*********************************************************************************************************************************/
54#if (defined(IN_RT_STATIC) || defined(IPRT_ERRMSG_DEFINES_ONLY)) && !defined(IPRT_ERRMSG_NO_FULL_MSG)
55/** Skip the full message in static builds to save space.
56 * This is defined when IPRT_ERRMSG_DEFINES_ONLY is defined. */
57# define IPRT_ERRMSG_NO_FULL_MSG
58#endif
59
60
61/*********************************************************************************************************************************
62* Global Variables *
63*********************************************************************************************************************************/
64#ifdef IPRT_NO_ERROR_DATA
65/* Cook data just for VINF_SUCCESS so that code below compiles fine. */
66static const char g_achStrTabData[] = { "VINF_SUCCESS" };
67static const RTBLDPROGSTRTAB g_StatusMsgStrTab = { g_achStrTabData, sizeof(g_achStrTabData) - 1, 0, NULL };
68static const struct
69{
70 int16_t iCode;
71 uint8_t offDefine;
72 uint8_t cchDefine;
73 uint8_t offMsgShort;
74 uint8_t cchMsgShort;
75 uint8_t offMsgFull;
76 uint8_t cchMsgFull;
77} g_aStatusMsgs[] =
78{
79 { VINF_SUCCESS, 0, 12, 0, 12, 0, 12, },
80};
81#elif defined(IPRT_ERRMSG_DEFINES_ONLY)
82# include "errmsgdata-only-defines.h"
83#elif defined(IPRT_ERRMSG_NO_FULL_MSG)
84# include "errmsgdata-no-full-msg.h"
85#else
86# include "errmsgdata-all.h"
87#endif
88
89
90/**
91 * Looks up the message table entry for @a rc.
92 *
93 * @returns index into g_aStatusMsgs on success, ~(size_t)0 if not found.
94 * @param rc The status code to locate the entry for.
95 */
96static size_t rtErrLookup(int rc)
97{
98 /*
99 * Perform binary search (duplicate code in rtErrWinLookup).
100 */
101 size_t iStart = 0;
102 size_t iEnd = RT_ELEMENTS(g_aStatusMsgs);
103 for (;;)
104 {
105 size_t i = iStart + (iEnd - iStart) / 2;
106 int const iCode = g_aStatusMsgs[i].iCode;
107 if (rc < iCode)
108 {
109 if (iStart < i)
110 iEnd = i;
111 else
112 break;
113 }
114 else if (rc > iCode)
115 {
116 i++;
117 if (i < iEnd)
118 iStart = i;
119 else
120 break;
121 }
122 else
123 return i;
124 }
125
126#ifdef RT_STRICT
127 for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++)
128 Assert(g_aStatusMsgs[i].iCode != rc);
129#endif
130
131 return ~(size_t)0;
132}
133
134
135RTDECL(bool) RTErrIsKnown(int rc)
136{
137 return rtErrLookup(rc) != ~(size_t)0;
138}
139RT_EXPORT_SYMBOL(RTErrIsKnown);
140
141
142RTDECL(ssize_t) RTErrQueryDefine(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
143{
144 size_t idx = rtErrLookup(rc);
145 if (idx != ~(size_t)0)
146 return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
147 g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
148 pszBuf, cbBuf);
149 if (fFailIfUnknown)
150 return VERR_NOT_FOUND;
151 return RTStrFormatU32(pszBuf, cbBuf, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
152}
153RT_EXPORT_SYMBOL(RTErrQueryDefine);
154
155
156/**
157 * Helper for rtErrQueryMsgNotFound.
158 */
159DECLINLINE(ssize_t) rtErrQueryCopyHelper(char **ppszBuf, size_t *pcbBuf, const char *pszSrc, size_t cchSrc, ssize_t cchRet)
160{
161 char *pszDst = *ppszBuf;
162 size_t cbDst = *pcbBuf;
163 if (cbDst > cchSrc)
164 {
165 memcpy(pszDst, pszSrc, cchSrc);
166 cbDst -= cchSrc;
167 pszDst += cchSrc;
168 cchRet += cchSrc;
169 *pszDst = '\0';
170 }
171 else
172 {
173 while (cbDst > 1 && cchSrc > 0)
174 {
175 *pszDst++ = *pszSrc++;
176 cchSrc--;
177 cbDst--;
178 }
179 if (cbDst > 0)
180 *pszDst = '\0';
181 cchRet = VERR_BUFFER_OVERFLOW;
182 }
183 *ppszBuf = pszDst;
184 *pcbBuf = cbDst;
185 return cchRet;
186}
187
188
189/**
190 * RTErrQueryMsgShort & RTErrQueryMsgFull helper.
191 */
192DECL_NO_INLINE(static, ssize_t) rtErrQueryMsgNotFound(int rc, char *pszBuf, size_t cbBuf)
193{
194 /* Unknown Status %d (%#x) */
195 ssize_t cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE("Unknown Status "), 0);
196 char szValue[64];
197 size_t cchValue = (size_t)RTStrFormatU32(szValue, sizeof(szValue), rc, 10, 0, 0, RTSTR_F_VALSIGNED);
198 cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, szValue, cchValue, cchRet);
199 cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE(" ("), cchRet);
200 cchValue = (size_t)RTStrFormatU32(szValue, sizeof(szValue), rc, 16, 0, 0, RTSTR_F_SPECIAL);
201 cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, szValue, cchValue, cchRet);
202 cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE(")"), cchRet);
203 return cchRet;
204}
205
206
207RTDECL(ssize_t) RTErrQueryMsgShort(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
208{
209 size_t idx = rtErrLookup(rc);
210 if (idx != ~(size_t)0)
211#ifdef IPRT_ERRMSG_DEFINES_ONLY
212 return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
213 g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
214 pszBuf, cbBuf);
215#else
216 return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
217 g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
218 pszBuf, cbBuf);
219#endif
220 if (fFailIfUnknown)
221 return VERR_NOT_FOUND;
222 return rtErrQueryMsgNotFound(rc, pszBuf, cbBuf);
223}
224RT_EXPORT_SYMBOL(RTErrQueryMsgShort);
225
226
227RTDECL(ssize_t) RTErrQueryMsgFull(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
228{
229#if defined(IPRT_ERRMSG_DEFINES_ONLY) || defined(IPRT_ERRMSG_NO_FULL_MSG)
230 return RTErrQueryMsgShort(rc, pszBuf, cbBuf, fFailIfUnknown);
231#else
232 size_t idx = rtErrLookup(rc);
233 if (idx != ~(size_t)0)
234 return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
235 g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
236 pszBuf, cbBuf);
237 if (fFailIfUnknown)
238 return VERR_NOT_FOUND;
239 return rtErrQueryMsgNotFound(rc, pszBuf, cbBuf);
240#endif
241}
242RT_EXPORT_SYMBOL(RTErrQueryMsgShort);
243
244
245RTDECL(size_t) RTErrFormatDefine(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
246{
247 size_t idx = rtErrLookup(rc);
248 if (idx != ~(size_t)0)
249 return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
250 g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
251 pfnOutput, pvArgOutput);
252 size_t cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
253 return pfnOutput(pvArgOutput, pszTmp, cchValue);
254}
255RT_EXPORT_SYMBOL(RTErrFormatDefine);
256
257
258/**
259 * RTErrFormatMsgShort & RTErrFormatMsgFull helper.
260 */
261static size_t rtErrFormatMsgNotFound(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
262{
263 size_t cchRet = pfnOutput(pvArgOutput, RT_STR_TUPLE("Unknown Status "));
264 size_t cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
265 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
266 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
267 cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 16, 0, 0, RTSTR_F_SPECIAL);
268 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
269 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(")"));
270 return cchRet;
271}
272
273
274RTDECL(size_t) RTErrFormatMsgShort(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
275{
276 size_t idx = rtErrLookup(rc);
277 if (idx != ~(size_t)0)
278#ifndef IPRT_ERRMSG_DEFINES_ONLY
279 return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
280 g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
281 pfnOutput, pvArgOutput);
282#else
283 return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
284 g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
285 pfnOutput, pvArgOutput);
286#endif
287 return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
288}
289RT_EXPORT_SYMBOL(RTErrFormatMsgShort);
290
291
292RTDECL(size_t) RTErrFormatMsgFull(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
293{
294#ifdef IPRT_ERRMSG_NO_FULL_MSG
295 return RTErrFormatMsgShort(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
296#else
297 size_t idx = rtErrLookup(rc);
298 if (idx != ~(size_t)0)
299 return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
300 g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
301 pfnOutput, pvArgOutput);
302 return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
303#endif
304}
305RT_EXPORT_SYMBOL(RTErrFormatMsgFull);
306
307
308RTDECL(size_t) RTErrFormatMsgAll(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
309{
310 size_t idx = rtErrLookup(rc);
311 if (idx != ~(size_t)0)
312 {
313 size_t cchValue;
314 size_t cchRet = RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
315 g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
316 pfnOutput, pvArgOutput);
317 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
318 cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
319 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
320#ifdef IPRT_ERRMSG_DEFINES_ONLY
321 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(")"));
322#elif defined(IPRT_ERRMSG_NO_FULL_MSG)
323 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(") - "));
324 cchRet += RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
325 g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
326 pfnOutput, pvArgOutput);
327#else
328 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(") - "));
329 cchRet += RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
330 g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
331 pfnOutput, pvArgOutput);
332#endif
333 return cchRet;
334 }
335 return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
336}
337RT_EXPORT_SYMBOL(RTErrFormatMsgAll);
338
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette