VirtualBox

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

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

GuestCtrl: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: GuestCtrlIO.cpp 38269 2011-08-01 17:22:10Z 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/** @todo Add exception handling for STL stuff! */
31
32GuestProcessStreamBlock::GuestProcessStreamBlock()
33{
34
35}
36
37GuestProcessStreamBlock::~GuestProcessStreamBlock()
38{
39 Clear();
40}
41
42/**
43 * Adds a key (if not existing yet).
44 *
45 * @return IPRT status code.
46 * @param pszKey Key name to add.
47 */
48int GuestProcessStreamBlock::AddKey(const char *pszKey)
49{
50 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
51 /** @todo Add check for already existing keys! (VERR_ALREADY_EXISTS). */
52 m_mapPairs[Utf8Str(pszKey)].pszValue = NULL;
53
54 return VINF_SUCCESS;
55}
56
57/**
58 * Destroys the currently stored stream pairs.
59 *
60 * @return IPRT status code.
61 */
62void GuestProcessStreamBlock::Clear()
63{
64 for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++)
65 {
66 if (it->second.pszValue)
67 RTMemFree(it->second.pszValue);
68 }
69
70 m_mapPairs.clear();
71}
72
73/**
74 * Returns a 64-bit signed integer of a specified key.
75 *
76 * @return IPRT status code. VERR_NOT_FOUND if key was not found.
77 * @param pszKey Name of key to get the value for.
78 * @param piVal Pointer to value to return.
79 */
80int GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal)
81{
82 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
83 AssertPtrReturn(piVal, VERR_INVALID_POINTER);
84 const char *pszValue = GetString(pszKey);
85 if (pszValue)
86 {
87 *piVal = RTStrToInt64(pszValue);
88 return VINF_SUCCESS;
89 }
90 return VERR_NOT_FOUND;
91}
92
93/**
94 * Returns a 64-bit integer of a specified key.
95 *
96 * @return int64_t Value to return, 0 if not found / on failure.
97 * @param pszKey Name of key to get the value for.
98 */
99int64_t GuestProcessStreamBlock::GetInt64(const char *pszKey)
100{
101 int64_t iVal;
102 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
103 return iVal;
104 return 0;
105}
106
107/**
108 * Returns the current number of stream pairs.
109 *
110 * @return uint32_t Current number of stream pairs.
111 */
112size_t GuestProcessStreamBlock::GetCount()
113{
114 return m_mapPairs.size();
115}
116
117
118/**
119 * Returns a string value of a specified key.
120 *
121 * @return uint32_t Pointer to string to return, NULL if not found / on failure.
122 * @param pszKey Name of key to get the value for.
123 */
124const char* GuestProcessStreamBlock::GetString(const char *pszKey)
125{
126 AssertPtrReturn(pszKey, NULL);
127
128 try
129 {
130 GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
131 if (itPairs != m_mapPairs.end())
132 return itPairs->second.pszValue;
133 }
134 catch (const std::exception &ex)
135 {
136 NOREF(ex);
137 }
138 return NULL;
139}
140
141/**
142 * Returns a 32-bit unsigned integer of a specified key.
143 *
144 * @return IPRT status code. VERR_NOT_FOUND if key was not found.
145 * @param pszKey Name of key to get the value for.
146 * @param puVal Pointer to value to return.
147 */
148int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
149{
150 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
151 AssertPtrReturn(puVal, VERR_INVALID_POINTER);
152 const char *pszValue = GetString(pszKey);
153 if (pszValue)
154 {
155 *puVal = RTStrToUInt32(pszValue);
156 return VINF_SUCCESS;
157 }
158 return VERR_NOT_FOUND;
159}
160
161/**
162 * Returns a 32-bit unsigned integer of a specified key.
163 *
164 * @return uint32_t Value to return, 0 if not found / on failure.
165 * @param pszKey Name of key to get the value for.
166 */
167uint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey)
168{
169 uint32_t uVal;
170 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
171 return uVal;
172 return 0;
173}
174
175/**
176 * Sets a value to a key or deletes a key by setting a NULL value.
177 *
178 * @return IPRT status code.
179 * @param pszKey Key name to process.
180 * @param pszValue Value to set. Set NULL for deleting the key.
181 */
182int GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue)
183{
184 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
185
186 int rc = VINF_SUCCESS;
187 if (pszValue)
188 {
189 char *pszVal = RTStrDup(pszValue);
190 if (pszVal)
191 m_mapPairs[pszKey].pszValue = pszVal;
192 else
193 rc = VERR_NO_MEMORY;
194 }
195 else
196 {
197 GuestCtrlStreamPairsIter it = m_mapPairs.find(pszKey);
198 if (it != m_mapPairs.end())
199 {
200 if (it->second.pszValue)
201 {
202 RTMemFree(it->second.pszValue);
203 it->second.pszValue = NULL;
204 }
205 m_mapPairs.erase(it);
206 }
207 }
208 return rc;
209}
210
211///////////////////////////////////////////////////////////////////////////////
212
213GuestProcessStream::GuestProcessStream()
214 : m_cbAllocated(0),
215 m_cbSize(0),
216 m_cbOffset(0),
217 m_pbBuffer(NULL)
218{
219
220}
221
222GuestProcessStream::~GuestProcessStream()
223{
224 Destroy();
225}
226
227/**
228 * Adds data to the internal parser buffer. Useful if there
229 * are multiple rounds of adding data needed.
230 *
231 * @return IPRT status code.
232 * @param pbData Pointer to data to add.
233 * @param cbData Size (in bytes) of data to add.
234 */
235int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
236{
237 AssertPtrReturn(pbData, VERR_INVALID_POINTER);
238 AssertReturn(cbData, VERR_INVALID_PARAMETER);
239
240 int rc = VINF_SUCCESS;
241
242 /* Rewind the buffer if it's empty. */
243 size_t cbInBuf = m_cbSize - m_cbOffset;
244 bool const fAddToSet = cbInBuf == 0;
245 if (fAddToSet)
246 m_cbSize = m_cbOffset = 0;
247
248 /* Try and see if we can simply append the data. */
249 if (cbData + m_cbSize <= m_cbAllocated)
250 {
251 memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
252 m_cbSize += cbData;
253 }
254 else
255 {
256 /* Move any buffered data to the front. */
257 cbInBuf = m_cbSize - m_cbOffset;
258 if (cbInBuf == 0)
259 m_cbSize = m_cbOffset = 0;
260 else if (m_cbOffset) /* Do we have something to move? */
261 {
262 memmove(m_pbBuffer, &m_pbBuffer[m_cbOffset], cbInBuf);
263 m_cbSize = cbInBuf;
264 m_cbOffset = 0;
265 }
266
267 /* Do we need to grow the buffer? */
268 if (cbData + m_cbSize > m_cbAllocated)
269 {
270 size_t cbAlloc = m_cbSize + cbData;
271 cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
272 void *pvNew = RTMemRealloc(m_pbBuffer, cbAlloc);
273 if (pvNew)
274 {
275 m_pbBuffer = (uint8_t *)pvNew;
276 m_cbAllocated = cbAlloc;
277 }
278 else
279 rc = VERR_NO_MEMORY;
280 }
281
282 /* Finally, copy the data. */
283 if (RT_SUCCESS(rc))
284 {
285 if (cbData + m_cbSize <= m_cbAllocated)
286 {
287 memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
288 m_cbSize += cbData;
289 }
290 else
291 rc = VERR_BUFFER_OVERFLOW;
292 }
293 }
294
295 return rc;
296}
297
298/**
299 * Destroys the the internal data buffer.
300 */
301void GuestProcessStream::Destroy()
302{
303 if (m_pbBuffer)
304 {
305 RTMemFree(m_pbBuffer);
306 m_pbBuffer = NULL;
307 }
308
309 m_cbAllocated = 0;
310 m_cbSize = 0;
311 m_cbOffset = 0;
312}
313
314/**
315 * Returns the current offset of the parser within
316 * the internal data buffer.
317 *
318 * @return uint32_t Parser offset.
319 */
320uint32_t GuestProcessStream::GetOffset()
321{
322 return m_cbOffset;
323}
324
325/**
326 * Try to parse the next upcoming pair block within the internal
327 * buffer. Old pairs from a previously parsed block will be removed first!
328 *
329 * @return IPRT status code.
330 */
331int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
332{
333 AssertPtrReturn(m_pbBuffer, VINF_SUCCESS);
334 AssertReturn(m_cbSize, VINF_SUCCESS);
335 AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER);
336
337 int rc = VINF_SUCCESS;
338
339 size_t uCur = m_cbOffset;
340 for (;uCur < m_cbSize;)
341 {
342 const char *pszStart = (char*)&m_pbBuffer[uCur];
343 const char *pszEnd = pszStart;
344
345 /* Search end of current pair (key=value\0). */
346 while (uCur++ < m_cbSize)
347 {
348 if (*pszEnd == '\0')
349 break;
350 pszEnd++;
351 }
352
353 size_t uPairLen = pszEnd - pszStart;
354 if (uPairLen)
355 {
356 const char *pszSep = pszStart;
357 while ( *pszSep != '='
358 && pszSep != pszEnd)
359 {
360 pszSep++;
361 }
362
363 /* No separator found (or incomplete key=value pair)? */
364 if ( pszSep == pszStart
365 || pszSep == pszEnd)
366 {
367 m_cbOffset = uCur - uPairLen - 1;
368 rc = VERR_MORE_DATA;
369 }
370
371 if (RT_FAILURE(rc))
372 break;
373
374 size_t uKeyLen = pszSep - pszStart;
375 size_t uValLen = pszEnd - (pszSep + 1);
376
377 /* Get key (if present). */
378 if (uKeyLen)
379 {
380 Assert(pszSep > pszStart);
381 char *pszKey = (char*)RTMemAllocZ(uKeyLen + 1);
382 if (!pszKey)
383 {
384 rc = VERR_NO_MEMORY;
385 break;
386 }
387 memcpy(pszKey, pszStart, uKeyLen);
388
389 streamBlock.AddKey(pszKey);
390
391 /* Get value (if present). */
392 if (uValLen)
393 {
394 Assert(pszEnd > pszSep);
395 char *pszVal = (char*)RTMemAllocZ(uValLen + 1);
396 if (!pszVal)
397 {
398 rc = VERR_NO_MEMORY;
399 break;
400 }
401 memcpy(pszVal, pszSep + 1, uValLen);
402
403 streamBlock.SetValue(pszKey, pszVal);
404 RTMemFree(pszVal);
405 }
406
407 RTMemFree(pszKey);
408
409 m_cbOffset += uCur - m_cbOffset;
410 }
411 }
412 else /* No pair detected, check for a new block. */
413 {
414 do
415 {
416 if (*pszEnd == '\0')
417 {
418 m_cbOffset = uCur;
419 rc = VERR_MORE_DATA;
420 break;
421 }
422 pszEnd++;
423 } while (++uCur < m_cbSize);
424 }
425
426 if (RT_FAILURE(rc))
427 break;
428 }
429
430 RT_CLAMP(m_cbOffset, 0, m_cbSize);
431
432 return rc;
433}
434
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