9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/** @file
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * VBox HDD container test utility - scripting engine, internal stack implementation.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/*
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Copyright (C) 2013 Oracle Corporation
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * General Public License (GPL) as published by the Free Software
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#ifndef _VDScriptStack_h__
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#define _VDScriptStack_h__
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#include <iprt/list.h>
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#include <iprt/string.h>
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#include "VDScript.h"
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Stack structure.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsynctypedef struct VDSCRIPTSTACK
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync /** Size of one stack element. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync size_t cbStackEntry;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync /** Stack memory. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync void *pvStack;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync /** Number of elements on the stack. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync unsigned cOnStack;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync /** Maximum number of elements the stack can hold. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync unsigned cOnStackMax;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync} VDSCRIPTSTACK;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/** Pointer to a stack. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsynctypedef VDSCRIPTSTACK *PVDSCRIPTSTACK;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Init the stack structure.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @returns nothing.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param pStack The stack to initialize.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param cbStackEntry The size of one stack entry.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsyncDECLINLINE(void) vdScriptStackInit(PVDSCRIPTSTACK pStack, size_t cbStackEntry)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cbStackEntry = cbStackEntry;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->pvStack = NULL;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cOnStack = 0;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cOnStackMax = 0;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync}
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
5606210c3e3213a247418d91961ef5380fc87640vboxsync/**
5606210c3e3213a247418d91961ef5380fc87640vboxsync * Destroys the given stack freeing all memory.
5606210c3e3213a247418d91961ef5380fc87640vboxsync *
5606210c3e3213a247418d91961ef5380fc87640vboxsync * @returns nothing.
5606210c3e3213a247418d91961ef5380fc87640vboxsync * @param pStack The stack to destroy.
5606210c3e3213a247418d91961ef5380fc87640vboxsync */
5606210c3e3213a247418d91961ef5380fc87640vboxsyncDECLINLINE(void) vdScriptStackDestroy(PVDSCRIPTSTACK pStack)
5606210c3e3213a247418d91961ef5380fc87640vboxsync{
5606210c3e3213a247418d91961ef5380fc87640vboxsync if (pStack->pvStack)
5606210c3e3213a247418d91961ef5380fc87640vboxsync RTMemFree(pStack->pvStack);
5606210c3e3213a247418d91961ef5380fc87640vboxsync pStack->cbStackEntry = 0;
5606210c3e3213a247418d91961ef5380fc87640vboxsync pStack->pvStack = NULL;
5606210c3e3213a247418d91961ef5380fc87640vboxsync pStack->cOnStack = 0;
5606210c3e3213a247418d91961ef5380fc87640vboxsync pStack->cOnStackMax = 0;
5606210c3e3213a247418d91961ef5380fc87640vboxsync}
5606210c3e3213a247418d91961ef5380fc87640vboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Gets the topmost unused stack entry.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @returns Pointer to the first unused entry.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * NULL if there is no room left and increasing the stack failed.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param pStack The stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsyncDECLINLINE(void *)vdScriptStackGetUnused(PVDSCRIPTSTACK pStack)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync void *pvElem = NULL;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync if (pStack->cOnStack >= pStack->cOnStackMax)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync {
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync unsigned cOnStackMaxNew = pStack->cOnStackMax + 10;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync void *pvStackNew = NULL;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync /* Try to increase stack space. */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pvStackNew = RTMemRealloc(pStack->pvStack, cOnStackMaxNew * pStack->cbStackEntry);
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync if (pvStackNew)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync {
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->pvStack = pvStackNew;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cOnStackMax = cOnStackMaxNew;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync }
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync }
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
5606210c3e3213a247418d91961ef5380fc87640vboxsync if (pStack->cOnStack < pStack->cOnStackMax)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pvElem = (char *)pStack->pvStack + pStack->cOnStack * pStack->cbStackEntry;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync return pvElem;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync}
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Gets the topmost used entry on the stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @returns Pointer to the first used entry
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * or NULL if the stack is empty.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param pStack The stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsyncDECLINLINE(void *)vdScriptStackGetUsed(PVDSCRIPTSTACK pStack)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync if (!pStack->cOnStack)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync return NULL;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync else
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync return (char *)pStack->pvStack + (pStack->cOnStack - 1) * pStack->cbStackEntry;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync}
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Increases the used element count for the given stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @returns nothing.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param pStack The stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsyncDECLINLINE(void) vdScriptStackPush(PVDSCRIPTSTACK pStack)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cOnStack++;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync}
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync/**
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * Decreases the used element count for the given stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync *
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @returns nothing.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync * @param pStack The stack.
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync */
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsyncDECLINLINE(void) vdScriptStackPop(PVDSCRIPTSTACK pStack)
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync{
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync pStack->cOnStack--;
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync}
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync
9e0b97c99123f5eb89a851ce0182f7e438000c0dvboxsync#endif /* _VDScriptStack_h__ */