VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/path/RTPathSplit.cpp@ 93115

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.2 KB
Line 
1/* $Id: RTPathSplit.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT - RTPathSplit
4 */
5
6/*
7 * Copyright (C) 2013-2022 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 "internal/iprt.h"
32#include <iprt/path.h>
33
34#include <iprt/assert.h>
35#include <iprt/err.h>
36#include <iprt/string.h>
37
38
39
40RTDECL(int) RTPathSplit(const char *pszPath, PRTPATHSPLIT pSplit, size_t cbSplit, uint32_t fFlags)
41{
42 /*
43 * Input validation.
44 */
45 AssertReturn(cbSplit >= RT_UOFFSETOF(RTPATHSPLIT, apszComps), VERR_INVALID_PARAMETER);
46 AssertPtrReturn(pSplit, VERR_INVALID_POINTER);
47 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
48 AssertReturn(*pszPath, VERR_PATH_ZERO_LENGTH);
49 AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), VERR_INVALID_FLAGS);
50
51 /*
52 * Use RTPathParse to do the parsing.
53 * - This makes the ASSUMPTION that the output of this function is greater
54 * or equal to that of RTPathParsed.
55 * - We're aliasing the buffer here, so use volatile to avoid issues due to
56 * compiler optimizations.
57 */
58 RTPATHPARSED volatile *pParsedVolatile = (RTPATHPARSED volatile *)pSplit;
59 RTPATHSPLIT volatile *pSplitVolatile = (RTPATHSPLIT volatile *)pSplit;
60
61 AssertCompile(sizeof(*pParsedVolatile) <= sizeof(*pSplitVolatile));
62 AssertCompile(sizeof(pParsedVolatile->aComps[0]) <= sizeof(pSplitVolatile->apszComps[0]));
63
64 int rc = RTPathParse(pszPath, (PRTPATHPARSED)pParsedVolatile, cbSplit, fFlags);
65 if (RT_FAILURE(rc) && rc != VERR_BUFFER_OVERFLOW)
66 return rc;
67
68 /*
69 * Calculate the required buffer space.
70 */
71 uint16_t const cComps = pParsedVolatile->cComps;
72 uint16_t const fProps = pParsedVolatile->fProps;
73 uint16_t const cchPath = pParsedVolatile->cchPath;
74 uint16_t const offSuffix = pParsedVolatile->offSuffix;
75 uint32_t cbNeeded = RT_UOFFSETOF_DYN(RTPATHSPLIT, apszComps[cComps])
76 + cchPath
77 + RTPATH_PROP_FIRST_NEEDS_NO_SLASH(fProps) /* zero terminator for root spec. */
78 - RT_BOOL(fProps & RTPATH_PROP_DIR_SLASH) /* counted by cchPath, not included in the comp str. */
79 + 1; /* zero terminator. */
80 if (cbNeeded > cbSplit)
81 {
82 pSplitVolatile->cbNeeded = cbNeeded;
83 return VERR_BUFFER_OVERFLOW;
84 }
85 Assert(RT_SUCCESS(rc));
86
87 /*
88 * Convert the array and copy the strings, both backwards.
89 */
90 char *psz = (char *)pSplit + cbNeeded;
91 uint32_t idxComp = cComps - 1;
92
93 /* the final component first (because of suffix handling). */
94 uint16_t offComp = pParsedVolatile->aComps[idxComp].off;
95 uint16_t cchComp = pParsedVolatile->aComps[idxComp].cch;
96
97 *--psz = '\0';
98 psz -= cchComp;
99 memcpy(psz, &pszPath[offComp], cchComp);
100 pSplitVolatile->apszComps[idxComp] = psz;
101
102 char *pszSuffix;
103 if (offSuffix >= offComp + cchComp)
104 pszSuffix = &psz[cchComp];
105 else
106 pszSuffix = &psz[offSuffix - offComp];
107
108 /* the remainder */
109 while (idxComp-- > 0)
110 {
111 offComp = pParsedVolatile->aComps[idxComp].off;
112 cchComp = pParsedVolatile->aComps[idxComp].cch;
113 *--psz = '\0';
114 psz -= cchComp;
115 memcpy(psz, &pszPath[offComp], cchComp);
116 pSplitVolatile->apszComps[idxComp] = psz;
117 }
118
119 /*
120 * Store / reshuffle the non-array bits. This MUST be done after finishing
121 * the array processing because there may be members in RTPATHSPLIT
122 * overlapping the array of RTPATHPARSED.
123 */
124 AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cComps, RTPATHSPLIT, cComps); Assert(pSplitVolatile->cComps == cComps);
125 AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, fProps, RTPATHSPLIT, fProps); Assert(pSplitVolatile->fProps == fProps);
126 AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cchPath, RTPATHSPLIT, cchPath); Assert(pSplitVolatile->cchPath == cchPath);
127 pSplitVolatile->u16Reserved = 0;
128 pSplitVolatile->cbNeeded = cbNeeded;
129 pSplitVolatile->pszSuffix = pszSuffix;
130
131 return rc;
132}
133
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