VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp@ 38210

Last change on this file since 38210 was 38210, checked in by vboxsync, 14 years ago

Main: Testcase for guest control output buffer parsing now is using the same code as GuestCtrlIO.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: GuestCtrlIO.cpp 38210 2011-07-28 08:42:59Z vboxsync $ */
2/** @file
3 *
4 * IO helper for IGuest COM class implementations.
5 */
6
7/*
8 * Copyright (C) 2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/******************************************************************************
20 * Header Files *
21 ******************************************************************************/
22#include "GuestCtrlImplPrivate.h"
23
24
25/******************************************************************************
26 * Structures and Typedefs *
27 ******************************************************************************/
28
29/** @todo *NOT* thread safe yet! */
30
31GuestProcessStream::GuestProcessStream()
32 : m_cbAllocated(0),
33 m_cbSize(0),
34 m_cbOffset(0),
35 m_cbParserOffset(0),
36 m_pbBuffer(NULL)
37{
38
39}
40
41GuestProcessStream::~GuestProcessStream()
42{
43 Destroy();
44}
45
46
47int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
48{
49 AssertPtrReturn(pbData, VERR_INVALID_POINTER);
50 AssertReturn(cbData, VERR_INVALID_PARAMETER);
51
52 int rc = VINF_SUCCESS;
53
54 /* Rewind the buffer if it's empty. */
55 size_t cbInBuf = m_cbSize - m_cbOffset;
56 bool const fAddToSet = cbInBuf == 0;
57 if (fAddToSet)
58 m_cbSize = m_cbOffset = 0;
59
60 /* Try and see if we can simply append the data. */
61 if (cbData + m_cbSize <= m_cbAllocated)
62 {
63 memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
64 m_cbSize += cbData;
65 }
66 else
67 {
68 /* Move any buffered data to the front. */
69 cbInBuf = m_cbSize - m_cbOffset;
70 if (cbInBuf == 0)
71 m_cbSize = m_cbOffset = 0;
72 else if (m_cbOffset) /* Do we have something to move? */
73 {
74 memmove(m_pbBuffer, &m_pbBuffer[m_cbOffset], cbInBuf);
75 m_cbSize = cbInBuf;
76 m_cbOffset = 0;
77 }
78
79 /* Do we need to grow the buffer? */
80 if (cbData + m_cbSize > m_cbAllocated)
81 {
82 size_t cbAlloc = m_cbSize + cbData;
83 cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
84 void *pvNew = RTMemRealloc(m_pbBuffer, cbAlloc);
85 if (pvNew)
86 {
87 m_pbBuffer = (uint8_t *)pvNew;
88 m_cbAllocated = cbAlloc;
89 }
90 else
91 rc = VERR_NO_MEMORY;
92 }
93
94 /* Finally, copy the data. */
95 if (RT_SUCCESS(rc))
96 {
97 if (cbData + m_cbSize <= m_cbAllocated)
98 {
99 memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
100 m_cbSize += cbData;
101 }
102 else
103 rc = VERR_BUFFER_OVERFLOW;
104 }
105 }
106
107 return rc;
108}
109
110void GuestProcessStream::ClearPairs()
111{
112 for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++)
113 {
114 if (it->second.pszValue)
115 RTMemFree(it->second.pszValue);
116 }
117
118 m_mapPairs.clear();
119}
120
121/**
122 * Destroys the stored stream pairs.
123 */
124void GuestProcessStream::Destroy()
125{
126 ClearPairs();
127
128 if (m_pbBuffer)
129 RTMemFree(m_pbBuffer);
130}
131
132int GuestProcessStream::GetInt64Ex(const char *pszKey, int64_t *piVal)
133{
134 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
135 AssertPtrReturn(piVal, VERR_INVALID_POINTER);
136 const char *pszValue = GetString(pszKey);
137 if (pszValue)
138 {
139 *piVal = RTStrToInt64(pszValue);
140 return VINF_SUCCESS;
141 }
142 return VERR_NOT_FOUND;
143}
144
145/**
146 * Returns a 64-bit integer of a specified key.
147 *
148 * @return int64_t Value to return, 0 if not found / on failure.
149 * @param pszKey Name of key to get the value for.
150 */
151int64_t GuestProcessStream::GetInt64(const char *pszKey)
152{
153 int64_t iVal;
154 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
155 return iVal;
156 return 0;
157}
158
159/**
160 * Returns the current number of stream pairs.
161 *
162 * @return uint32_t Current number of stream pairs.
163 */
164size_t GuestProcessStream::GetNumPairs()
165{
166 return m_mapPairs.size();
167}
168
169uint32_t GuestProcessStream::GetOffset()
170{
171 return m_cbOffset;
172}
173
174/**
175 * Returns a 32-bit unsigned integer of a specified key.
176 *
177 * @return uint32_t Value to return, 0 if not found / on failure.
178 * @param pszKey Name of key to get the value for.
179 */
180const char* GuestProcessStream::GetString(const char *pszKey)
181{
182 AssertPtrReturn(pszKey, NULL);
183
184 try
185 {
186 GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
187 if (itPairs != m_mapPairs.end())
188 return itPairs->second.pszValue;
189 }
190 catch (const std::exception &ex)
191 {
192 NOREF(ex);
193 }
194 return NULL;
195}
196
197int GuestProcessStream::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
198{
199 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
200 AssertPtrReturn(puVal, VERR_INVALID_POINTER);
201 const char *pszValue = GetString(pszKey);
202 if (pszValue)
203 {
204 *puVal = RTStrToUInt32(pszValue);
205 return VINF_SUCCESS;
206 }
207 return VERR_NOT_FOUND;
208}
209
210/**
211 * Returns a 32-bit unsigned integer of a specified key.
212 *
213 * @return uint32_t Value to return, 0 if not found / on failure.
214 * @param pszKey Name of key to get the value for.
215 */
216uint32_t GuestProcessStream::GetUInt32(const char *pszKey)
217{
218 uint32_t uVal;
219 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
220 return uVal;
221 return 0;
222}
223
224int GuestProcessStream::Parse()
225{
226 AssertPtrReturn(m_pbBuffer, VINF_SUCCESS);
227 AssertReturn(m_cbSize, VINF_SUCCESS);
228 AssertReturn(m_cbParserOffset < m_cbSize, VERR_INVALID_PARAMETER);
229
230 int rc = VINF_SUCCESS;
231
232 size_t uCur = m_cbParserOffset;
233 for (;uCur < m_cbSize;)
234 {
235 const char *pszStart = (char*)&m_pbBuffer[uCur];
236 const char *pszEnd = pszStart;
237
238 /* Search end of current pair (key=value\0). */
239 while (uCur++ < m_cbSize)
240 {
241 if (*pszEnd == '\0')
242 break;
243 pszEnd++;
244 }
245
246 size_t uPairLen = pszEnd - pszStart;
247 if (uPairLen)
248 {
249 const char *pszSep = pszStart;
250 while ( *pszSep != '='
251 && pszSep != pszEnd)
252 {
253 pszSep++;
254 }
255
256 /* No separator found (or incomplete key=value pair)? */
257 if ( pszSep == pszStart
258 || pszSep == pszEnd)
259 {
260 m_cbParserOffset = uCur - uPairLen - 1;
261 rc = VERR_MORE_DATA;
262 }
263
264 if (RT_FAILURE(rc))
265 break;
266
267 size_t uKeyLen = pszSep - pszStart;
268 size_t uValLen = pszEnd - (pszSep + 1);
269
270 /* Get key (if present). */
271 if (uKeyLen)
272 {
273 Assert(pszSep > pszStart);
274 char *pszKey = (char*)RTMemAllocZ(uKeyLen + 1);
275 if (!pszKey)
276 {
277 rc = VERR_NO_MEMORY;
278 break;
279 }
280 memcpy(pszKey, pszStart, uKeyLen);
281
282 m_mapPairs[Utf8Str(pszKey)].pszValue = NULL;
283
284 /* Get value (if present). */
285 if (uValLen)
286 {
287 Assert(pszEnd > pszSep);
288 char *pszVal = (char*)RTMemAllocZ(uValLen + 1);
289 if (!pszVal)
290 {
291 rc = VERR_NO_MEMORY;
292 break;
293 }
294 memcpy(pszVal, pszSep + 1, uValLen);
295
296 m_mapPairs[Utf8Str(pszKey)].pszValue = pszVal;
297 }
298
299 RTMemFree(pszKey);
300
301 m_cbParserOffset += uCur - m_cbParserOffset;
302 }
303 }
304 else /* No pair detected, check for a new block. */
305 {
306 do
307 {
308 if (*pszEnd == '\0')
309 {
310 m_cbParserOffset = uCur;
311 rc = VERR_MORE_DATA;
312 break;
313 }
314 pszEnd++;
315 } while (++uCur < m_cbSize);
316 }
317
318 if (RT_FAILURE(rc))
319 break;
320 }
321
322 RT_CLAMP(m_cbParserOffset, 0, m_cbSize);
323
324 return rc;
325}
326
Note: See TracBrowser for help on using the repository browser.

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