VirtualBox

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

Last change on this file since 86120 was 84063, checked in by vboxsync, 5 years ago

IPRT,++: New RTErrWin* API, data source unchanged. bugref:9726

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