VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/getoptargv.cpp@ 27128

Last change on this file since 27128 was 26525, checked in by vboxsync, 15 years ago

Runtime: win.amd64 warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: getoptargv.cpp 26525 2010-02-15 03:33:33Z vboxsync $ */
2/** @file
3 * IPRT - Command Line Parsing, Argument Vector.
4 */
5
6/*
7 * Copyright (C) 2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/getopt.h>
35#include "internal/iprt.h"
36
37#include <iprt/assert.h>
38#include <iprt/err.h>
39#include <iprt/mem.h>
40#include <iprt/string.h>
41
42
43/**
44 * Look for an unicode code point in the separator string.
45 *
46 * @returns true if it's a separator, false if it isn't.
47 * @param Cp The code point.
48 * @param pszSeparators The separators.
49 */
50static bool rtGetOptIsUniCpInString(RTUNICP Cp, const char *pszSeparators)
51{
52 /* This could be done in a more optimal fashion. Probably worth a
53 separate RTStr function at some point. */
54 for (;;)
55 {
56 RTUNICP CpSep;
57 int rc = RTStrGetCpEx(&pszSeparators, &CpSep);
58 AssertRCReturn(rc, false);
59 if (CpSep == Cp)
60 return true;
61 if (!CpSep)
62 return false;
63 }
64}
65
66
67/**
68 * Look for an 7-bit ASCII character in the separator string.
69 *
70 * @returns true if it's a separator, false if it isn't.
71 * @param ch The character.
72 * @param pszSeparators The separators.
73 * @param cchSeparators The number of separators chars.
74 */
75DECLINLINE(bool) rtGetOptIsAsciiInSet(char ch, const char *pszSeparators, size_t cchSeparators)
76{
77 switch (cchSeparators)
78 {
79 case 8: if (ch == pszSeparators[7]) return true;
80 case 7: if (ch == pszSeparators[6]) return true;
81 case 6: if (ch == pszSeparators[5]) return true;
82 case 5: if (ch == pszSeparators[4]) return true;
83 case 4: if (ch == pszSeparators[3]) return true;
84 case 3: if (ch == pszSeparators[2]) return true;
85 case 2: if (ch == pszSeparators[1]) return true;
86 case 1: if (ch == pszSeparators[0]) return true;
87 return false;
88 default:
89 return memchr(pszSeparators, ch, cchSeparators) != NULL;
90 }
91}
92
93
94/**
95 * Checks if the character is in the set of separators
96 *
97 * @returns true if it is, false if it isn't.
98 *
99 * @param Cp The code point.
100 * @param pszSeparators The separators.
101 * @param cchSeparators The length of @a pszSeparators.
102 */
103DECL_FORCE_INLINE(bool) rtGetOptIsCpInSet(RTUNICP Cp, const char *pszSeparators, size_t cchSeparators)
104{
105 if (RT_LIKELY(Cp <= 127))
106 return rtGetOptIsAsciiInSet((char)Cp, pszSeparators, cchSeparators);
107 return rtGetOptIsUniCpInString(Cp, pszSeparators);
108}
109
110
111/**
112 * Skips any delimiters at the start of the string that is pointed to.
113 *
114 * @returns VINF_SUCCESS or RTStrGetCpEx status code.
115 * @param ppszSrc Where to get and return the string pointer.
116 * @param pszSeparators The separators.
117 * @param cchSeparators The length of @a pszSeparators.
118 */
119static int rtGetOptSkipDelimiters(const char **ppszSrc, const char *pszSeparators, size_t cchSeparators)
120{
121 const char *pszSrc = *ppszSrc;
122 const char *pszRet;
123 for (;;)
124 {
125 pszRet = pszSrc;
126 RTUNICP Cp;
127 int rc = RTStrGetCpEx(&pszSrc, &Cp);
128 if (RT_FAILURE(rc))
129 {
130 *ppszSrc = pszRet;
131 return rc;
132 }
133 if ( !Cp
134 || !rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
135 break;
136 }
137
138 *ppszSrc = pszRet;
139 return VINF_SUCCESS;
140}
141
142
143RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators)
144{
145 /*
146 * Some input validation.
147 */
148 AssertPtr(pszCmdLine);
149 AssertPtr(pcArgs);
150 AssertPtr(ppapszArgv);
151 if (!pszSeparators)
152 pszSeparators = " \t\n\r";
153 else
154 AssertPtr(pszSeparators);
155 size_t const cchSeparators = strlen(pszSeparators);
156 AssertReturn(cchSeparators > 0, VERR_INVALID_PARAMETER);
157
158 /*
159 * Parse the command line and chop off it into argv individual argv strings.
160 */
161 int rc = VINF_SUCCESS;
162 const char *pszSrc = pszCmdLine;
163 char *pszDup = (char *)RTMemAlloc(strlen(pszSrc) + 1);
164 char *pszDst = pszDup;
165 if (!pszDup)
166 return VERR_NO_STR_MEMORY;
167 char **papszArgs = NULL;
168 unsigned iArg = 0;
169 while (*pszSrc)
170 {
171 /* Skip stuff */
172 rc = rtGetOptSkipDelimiters(&pszSrc, pszSeparators, cchSeparators);
173 if (RT_FAILURE(rc))
174 break;
175 if (!*pszSrc)
176 break;
177
178 /* Start a new entry. */
179 if ((iArg % 32) == 0)
180 {
181 void *pvNew = RTMemRealloc(papszArgs, (iArg + 33) * sizeof(char *));
182 if (!pvNew)
183 {
184 rc = VERR_NO_MEMORY;
185 break;
186 }
187 papszArgs = (char **)pvNew;
188 }
189 papszArgs[iArg++] = pszDst;
190
191 /* Parse and copy the string over. */
192 RTUNICP CpQuote = 0;
193 RTUNICP Cp;
194 for (;;)
195 {
196 rc = RTStrGetCpEx(&pszSrc, &Cp);
197 if (RT_FAILURE(rc) || !Cp)
198 break;
199 if (!CpQuote)
200 {
201 if (Cp == '"' || Cp == '\'')
202 CpQuote = Cp;
203 else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
204 break;
205 else
206 pszDst = RTStrPutCp(pszDst, Cp);
207 }
208 else if (CpQuote != Cp)
209 pszDst = RTStrPutCp(pszDst, Cp);
210 else
211 CpQuote = 0;
212 }
213 *pszDst++ = '\0';
214 if (RT_FAILURE(rc) || !Cp)
215 break;
216 }
217
218 if (RT_FAILURE(rc))
219 {
220 RTMemFree(pszDup);
221 RTMemFree(papszArgs);
222 return rc;
223 }
224
225 /*
226 * Terminate the array.
227 * Check for empty string to make sure we've got an array.
228 */
229 if (iArg == 0)
230 {
231 RTMemFree(pszDup);
232 papszArgs = (char **)RTMemAlloc(1 * sizeof(char *));
233 if (!papszArgs)
234 return VERR_NO_MEMORY;
235 }
236 papszArgs[iArg] = NULL;
237
238 *pcArgs = iArg;
239 *ppapszArgv = papszArgs;
240 return VINF_SUCCESS;
241}
242
243
244RTDECL(void) RTGetOptArgvFree(char **papszArgv)
245{
246 if (papszArgv)
247 {
248 RTMemFree(papszArgv[0]);
249 RTMemFree(papszArgv);
250 }
251}
252
253
254/** @todo RTGetOptArgvToString (for windows)?
255 * RTGetOptArgvSort for RTGetOptInit()? */
256
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