VirtualBox

source: vbox/trunk/include/iprt/bldprog-strtab.h@ 85416

Last change on this file since 85416 was 85254, checked in by vboxsync, 4 years ago

iprt/bldprog-strtab.h: Signed/unsigned conversion issues. bugref:9790

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/** @file
2 * IPRT - Build Program - String Table Generator, Accessors.
3 */
4
5/*
6 * Copyright (C) 2006-2020 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef IPRT_INCLUDED_bldprog_strtab_h
27#define IPRT_INCLUDED_bldprog_strtab_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/assert.h>
33#include <iprt/err.h>
34#include <iprt/string.h>
35
36
37/**
38 * The default build program string table reference.
39 */
40typedef struct RTBLDPROGSTRREF
41{
42 /** Offset of the string in the string table. */
43 uint32_t off : 22;
44 /** The length of the string. */
45 uint32_t cch : 10;
46} RTBLDPROGSTRREF;
47AssertCompileSize(RTBLDPROGSTRREF, sizeof(uint32_t));
48/** Pointer to a build program string table reference. */
49typedef RTBLDPROGSTRREF const *PCRTBLDPROGSTRREF;
50
51
52typedef struct RTBLDPROGSTRTAB
53{
54 const char *pchStrTab;
55 uint32_t cchStrTab;
56 uint8_t cCompDict;
57 PCRTBLDPROGSTRREF paCompDict;
58} RTBLDPROGSTRTAB;
59typedef const RTBLDPROGSTRTAB *PCRTBLDPROGSTRTAB;
60
61
62/**
63 * Tries to ensure the buffer is terminated when failing.
64 */
65DECLINLINE(ssize_t) RTBldProgStrTabQueryStringFail(int rc, char *pszDstStart, char *pszDst, size_t cbDst)
66{
67 if (cbDst)
68 *pszDst = '\0';
69 else if (pszDstStart != pszDst)
70 pszDst[-1] = '\0';
71 return rc;
72}
73
74
75/**
76 * Retrieves the decompressed string.
77 *
78 * @returns The string size on success, IPRT status code on failure.
79 * @param pStrTab The string table.
80 * @param offString The offset of the string.
81 * @param cchString The length of the string.
82 * @param pszDst The return buffer.
83 * @param cbDst The size of the return buffer.
84 */
85DECLINLINE(ssize_t) RTBldProgStrTabQueryString(PCRTBLDPROGSTRTAB pStrTab, uint32_t offString, size_t cchString,
86 char *pszDst, size_t cbDst)
87{
88 AssertReturn(offString < pStrTab->cchStrTab, VERR_OUT_OF_RANGE);
89 AssertReturn(offString + cchString <= pStrTab->cchStrTab, VERR_OUT_OF_RANGE);
90
91 if (pStrTab->cCompDict)
92 {
93 /*
94 * Could be compressed, decompress it.
95 */
96 char * const pchDstStart = pszDst;
97 const char *pchSrc = &pStrTab->pchStrTab[offString];
98 while (cchString-- > 0)
99 {
100 unsigned char uch = *(unsigned char *)pchSrc++;
101 if (!(uch & 0x80))
102 {
103 /*
104 * Plain text.
105 */
106 AssertReturn(cbDst > 1, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
107 cbDst -= 1;
108 *pszDst++ = (char)uch;
109 Assert(uch != 0);
110 }
111 else if (uch != 0xff)
112 {
113 /*
114 * Dictionary reference. (No UTF-8 unescaping necessary here.)
115 */
116 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch & 0x7f];
117 size_t const cchWord = pWord->cch;
118 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab,
119 RTBldProgStrTabQueryStringFail(VERR_INVALID_PARAMETER, pchDstStart, pszDst, cbDst));
120 AssertReturn(cbDst > cchWord,
121 RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
122 memcpy(pszDst, &pStrTab->pchStrTab[pWord->off], cchWord);
123 pszDst += cchWord;
124 cbDst -= cchWord;
125 }
126 else
127 {
128 /*
129 * UTF-8 encoded unicode codepoint.
130 */
131 size_t cchCp;
132 RTUNICP uc = ' ';
133 int rc = RTStrGetCpNEx(&pchSrc, &cchString, &uc);
134 AssertStmt(RT_SUCCESS(rc), (uc = '?', pchSrc++, cchString--));
135
136 cchCp = RTStrCpSize(uc);
137 AssertReturn(cbDst > cchCp,
138 RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
139
140 RTStrPutCp(pszDst, uc);
141 pszDst += cchCp;
142 cbDst -= cchCp;
143 }
144 }
145 AssertReturn(cbDst > 0, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
146 *pszDst = '\0';
147 return pszDst - pchDstStart;
148 }
149
150 /*
151 * Not compressed.
152 */
153 if (cbDst > cchString)
154 {
155 memcpy(pszDst, &pStrTab->pchStrTab[offString], cchString);
156 pszDst[cchString] = '\0';
157 return (ssize_t)cchString;
158 }
159 if (cbDst > 0)
160 {
161 memcpy(pszDst, &pStrTab->pchStrTab[offString], cbDst - 1);
162 pszDst[cbDst - 1] = '\0';
163 }
164 return VERR_BUFFER_OVERFLOW;
165}
166
167
168/**
169 * Outputs the decompressed string.
170 *
171 * @returns The sum of the pfnOutput return values.
172 * @param pStrTab The string table.
173 * @param offString The offset of the string.
174 * @param cchString The length of the string.
175 * @param pfnOutput The output function.
176 * @param pvArgOutput The argument to pass to the output function.
177 *
178 */
179DECLINLINE(size_t) RTBldProgStrTabQueryOutput(PCRTBLDPROGSTRTAB pStrTab, uint32_t offString, size_t cchString,
180 PFNRTSTROUTPUT pfnOutput, void *pvArgOutput)
181{
182 AssertReturn(offString < pStrTab->cchStrTab, 0);
183 AssertReturn(offString + cchString <= pStrTab->cchStrTab, 0);
184
185 if (pStrTab->cCompDict)
186 {
187 /*
188 * Could be compressed, decompress it.
189 */
190 size_t cchRet = 0;
191 const char *pchSrc = &pStrTab->pchStrTab[offString];
192 while (cchString-- > 0)
193 {
194 unsigned char uch = *(unsigned char *)pchSrc++;
195 if (!(uch & 0x80))
196 {
197 /*
198 * Plain text.
199 */
200 Assert(uch != 0);
201 cchRet += pfnOutput(pvArgOutput, (const char *)&uch, 1);
202 }
203 else if (uch != 0xff)
204 {
205 /*
206 * Dictionary reference. (No UTF-8 unescaping necessary here.)
207 */
208 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch & 0x7f];
209 size_t const cchWord = pWord->cch;
210 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, cchRet);
211
212 cchRet += pfnOutput(pvArgOutput, &pStrTab->pchStrTab[pWord->off], cchWord);
213 }
214 else
215 {
216 /*
217 * UTF-8 encoded unicode codepoint.
218 */
219 const char * const pchUtf8Seq = pchSrc;
220 RTUNICP uc = ' ';
221 int rc = RTStrGetCpNEx(&pchSrc, &cchString, &uc);
222 if (RT_SUCCESS(rc))
223 cchRet += pfnOutput(pvArgOutput, pchUtf8Seq, (size_t)(pchSrc - pchUtf8Seq));
224 else
225 cchRet += pfnOutput(pvArgOutput, "?", 1);
226 }
227 }
228 return cchRet;
229 }
230
231 /*
232 * Not compressed.
233 */
234 return pfnOutput(pvArgOutput, &pStrTab->pchStrTab[offString], cchString);
235}
236
237
238#endif /* !IPRT_INCLUDED_bldprog_strtab_h */
239
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